<?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>Mon, 23 Mar 2026 16:30:00 +0000</lastBuildDate>
      <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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;txt&quot; class=&quot;language-txt z-code&quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;.local&#x2F;share&#x2F;99managers-futsal-edition
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    local&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        settings_local.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        version.txt
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    sync&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        deleted_save_games.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        settings_sync.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        save_games&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            136907-518000-261045&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                checksums.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                cups.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                inbox.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                leagues.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&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 data-lang=&quot;txt&quot; class=&quot;language-txt z-code&quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;.local&#x2F;share&#x2F;99managers-futsal-edition
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    local&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        settings_local.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        settings_local.csv.backup1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        settings_local.csv.backup2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        version.txt
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    sync&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        deleted_save_games.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        deleted_save_games.csv.backup1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        deleted_save_games.csv.backup2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        settings_sync.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        settings_sync.csv.backup1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        settings_sync.csv.backup2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        save_games&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            136907-518000-261045&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                active&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                    checksums.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                    cups.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                    ...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                backup1&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                    checksums.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                    cups.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                    ...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                backup2&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                    checksums.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                    cups.csv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;lua&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;print&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_win_get_width&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-lua&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;full_screen&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-lua&quot;&gt;191&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; default status column, simply 2 spaces
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;statuscolumn&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;  &lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; status column if only one buffer is open
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; (full_screen - text width) &#x2F; 2
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;statuscolumn_wide&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-constant z-builtin z-lua&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;rep&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;quot;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;full_screen&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-lua&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-lua&quot;&gt;100&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-lua&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-lua&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-concatenation z-lua&quot;&gt;..&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;statuscolumn&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; set default
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;statuscolumn&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;statuscolumn&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; check window list count and adapt padding
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_create_autocmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;BufEnter&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;BufWinEnter&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;BufWinLeave&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;WinEnter&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;WinLeave&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;WinResized&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;VimResized&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-lua&quot;&gt;callback&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-lua&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;      &lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;winwidth&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_win_get_width&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-lua&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;      &lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;winwidth&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-lua&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;full_screen&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-lua&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-lua&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;statuscolumn&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;statuscolumn_wide&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;      &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;statuscolumn&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;statuscolumn&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;      &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arithmetic z-lua&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;l&lt;&#x2F;span&gt;	&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;line&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;number&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;of&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;currently&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;drawn&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;line&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arithmetic z-lua&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;r&lt;&#x2F;span&gt;	&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;relative&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;line&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;number&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;of&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;currently&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;drawn&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;line&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arithmetic z-lua&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;s&lt;&#x2F;span&gt;	&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;sign&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;column&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-lua&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;currently&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;drawn&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;line&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arithmetic z-lua&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;C&lt;&#x2F;span&gt;	&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;fold&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;column&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-lua&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;currently&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;drawn&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;statuscolumn&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;quot;&lt;&#x2F;span&gt; %l&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;help&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&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 data-lang=&quot;txt&quot; class=&quot;language-txt z-code&quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;WARNING: this expression is evaluated for each screen line so defining
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;an expensive expression can negatively affect render performance.
&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 data-lang=&quot;md&quot; class=&quot;language-md z-code&quot;&gt;&lt;code class=&quot;language-md&quot; data-lang=&quot;md&quot;&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-block-level z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-heading z-begin z-markdown&quot;&gt;#&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-heading z-1 z-markdown&quot;&gt;&lt;span class=&quot;z-entity z-name z-section z-markdown&quot;&gt;28.08 thu&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-whitespace z-newline z-markdown&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt; &lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;07:30
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt; 99 team logos
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt; 12:00
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt; &lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;13:00
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt; 99 team logos
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt; 16:00
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt; 99 new gameplay video
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt; 17:30
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt; &lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;18:00
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt; 99 new gameplay video
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt; 19:30
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt; &lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;21:00
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt; co upgrade to godot 4.4 and add keyboard support
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-html z-markdown&quot;&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-bullet z-markdown&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-list_item z-markdown&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-list z-unnumbered z-markdown&quot;&gt;&lt;span class=&quot;z-meta z-paragraph z-list z-markdown&quot;&gt; 23:30
&lt;&#x2F;span&gt;&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&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 data-lang=&quot;txt&quot; class=&quot;language-txt z-code&quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;There are only two hard things in Computer Science: cache invalidation and naming things.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;-- Phil Karlton
&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; access by unique name&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;label&lt;&#x2F;span&gt;: Label &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;%&lt;&#x2F;span&gt;Label
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; instead of full path&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;label&lt;&#x2F;span&gt;: Label &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; $MarginContainer&lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;&#x2F;&lt;&#x2F;span&gt;VBoxContainer&lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;&#x2F;&lt;&#x2F;span&gt;YetAnotherContainer&lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;&#x2F;&lt;&#x2F;span&gt;Label
&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; access by UID&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;scene&lt;&#x2F;span&gt;: PackedScene &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;load&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;uid:&#x2F;&#x2F;b48hr5ervcv&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; instead of full path&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;scene&lt;&#x2F;span&gt;: PackedScene &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;load&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;screens&#x2F;settings&#x2F;audio&#x2F;audio_settings.gd&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; add backports for kernel &amp;gt;6.2&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;deb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; http:&#x2F;&#x2F;deb.debian.org&#x2F;debian&#x2F; bookworm-backports main non-free-firmware&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;deb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; http:&#x2F;&#x2F;deb.debian.org&#x2F;debian&#x2F; bookworm main non-free-firmware&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;deb-src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; http:&#x2F;&#x2F;deb.debian.org&#x2F;debian&#x2F; bookworm main non-free-firmware&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;deb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; http:&#x2F;&#x2F;security.debian.org&#x2F;debian-security bookworm-security main non-free-firmware&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;deb-src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; http:&#x2F;&#x2F;security.debian.org&#x2F;debian-security bookworm-security main non-free-firmware&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; bookworm-updates, to get updates before a point release is made;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&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;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;deb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; http:&#x2F;&#x2F;deb.debian.org&#x2F;debian&#x2F; bookworm-updates main non-free-firmware&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;deb-src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; http:&#x2F;&#x2F;deb.debian.org&#x2F;debian&#x2F; bookworm-updates main non-free-firmware&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; update&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;t&lt;&#x2F;span&gt; bookworm-backports 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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;dulvui@rook:&lt;span class=&quot;z-meta z-group z-expansion z-tilde&quot;&gt;&lt;span class=&quot;z-variable z-language z-tilde z-shell&quot;&gt;~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; uname&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Linux&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; rook 6.12.32+bpo-amd64 &lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&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;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install 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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print_orphan_nodes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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 data-lang=&quot;txt&quot; class=&quot;language-txt z-code&quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;142639892262 - Stray Node: @BoxContainer@6 (Type: BoxContainer)
&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 data-lang=&quot;txt&quot; class=&quot;language-txt z-code&quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;122456901315 - Stray Node:  (Type: Node)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;122591119050 - Stray Node:  (Type: Node)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;130929395586 - Stray Node:  (Type: Node)
&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;data_util&lt;&#x2F;span&gt;: DataUtil &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; DataUtil.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;class_name DataUtil
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Node&lt;&#x2F;span&gt; &lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; 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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;class_name NoExtends
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_class&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; 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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;class_name WithExtends
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; RefCounted&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_class&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; 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&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&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Node&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;load all scenes...&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;scene_paths&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-container z-gdscript&quot;&gt;Array&lt;&#x2F;span&gt;[&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;] &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;find_files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; load scripts and check for possible dependency errors while loading&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;for&lt;&#x2F;span&gt; path: &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-gdscript&quot;&gt;in&lt;&#x2F;span&gt; scene_paths:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;TestScene&lt;&#x2F;span&gt;: PackedScene &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;load&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;path&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;TestScene &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;!=&lt;&#x2F;span&gt; null&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;instance&lt;&#x2F;span&gt;: Node &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; TestScene.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;instantiate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;instance &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;!=&lt;&#x2F;span&gt; null&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;load all scene done.&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;load all scripts...&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;script_paths&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-container z-gdscript&quot;&gt;Array&lt;&#x2F;span&gt;[&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;] &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;find_files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.gd&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; load scripts and check for possible runtime errors while loading&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;for&lt;&#x2F;span&gt; path: &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-gdscript&quot;&gt;in&lt;&#x2F;span&gt; script_paths:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;TestScript&lt;&#x2F;span&gt;: GDScript &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;load&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;path&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;TestScript &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;!=&lt;&#x2F;span&gt; null&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;load all scripts done.&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;find_files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;suffix&lt;&#x2F;span&gt;: &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameters z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;path&lt;&#x2F;span&gt;: &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;String&lt;&#x2F;span&gt; = &amp;quot;&lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;res&lt;&#x2F;span&gt;:&#x2F;&#x2F;&amp;quot;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-container z-gdscript&quot;&gt;Array&lt;&#x2F;span&gt;[&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;]&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;scripts&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-container z-gdscript&quot;&gt;Array&lt;&#x2F;span&gt;[&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;] &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; []
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;dir&lt;&#x2F;span&gt;: DirAccess &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; DirAccess.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;open&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;path&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;if&lt;&#x2F;span&gt; dir &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;null&lt;&#x2F;span&gt;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;error while opening %s&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;%&lt;&#x2F;span&gt; path&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;return&lt;&#x2F;span&gt; scripts
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	dir.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;list_dir_begin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;file_name&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; dir.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_next&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;while&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-gdscript&quot;&gt;not&lt;&#x2F;span&gt; file_name.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;is_empty&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;full_path&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; path &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+&lt;&#x2F;span&gt; file_name
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;if&lt;&#x2F;span&gt; dir.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;current_is_dir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			scripts.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;append_array&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;find_files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;suffix&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; full_path &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;elif&lt;&#x2F;span&gt; file_name.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;ends_with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;suffix&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			scripts.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;append&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;full_path&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		file_name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; dir.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_next&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;return&lt;&#x2F;span&gt; scripts
&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;class_name Player
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Resource&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;name&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;surname&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; custom resources need a _init() method with default values&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; to work as expected inside Godot&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;p_name&lt;&#x2F;span&gt;: &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;String&lt;&#x2F;span&gt; = &amp;quot;&amp;quot;&lt;span class=&quot;z-punctuation z-separator z-parameters z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;p_surname&lt;&#x2F;span&gt;: &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;String&lt;&#x2F;span&gt; = &amp;quot;&amp;quot;&lt;span class=&quot;z-punctuation z-separator z-parameters z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; p_name
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    surname &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; p_surname
&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;player_1&lt;&#x2F;span&gt;: Player &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; Player.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Gianluigi&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Buffon&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;player_2&lt;&#x2F;span&gt;: Player &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; player_1
&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; True, since both have the same RIDs&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;player_1.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_rid&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;==&lt;&#x2F;span&gt; player_2.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_rid&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;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;z-source z-gdscript&quot;&gt;player_1.name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Alessandro&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;player_1.surname &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Del Piero&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; True, because both variables point to the changed resource&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;player_1.surname &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;==&lt;&#x2F;span&gt; player_2.surname&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;class_name Team
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Resource&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;name&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;goalkeeper&lt;&#x2F;span&gt;: Player
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;field_players&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-container z-gdscript&quot;&gt;Array&lt;&#x2F;span&gt;[Player]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_init&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;p_name&lt;&#x2F;span&gt;: &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;String&lt;&#x2F;span&gt; = &amp;quot;&amp;quot;&lt;span class=&quot;z-punctuation z-separator z-parameters z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;    &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;p_goalkeeper&lt;&#x2F;span&gt;: &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;Player&lt;&#x2F;span&gt; = &lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;Player&lt;&#x2F;span&gt;.&lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;    p_field_players&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-container z-gdscript&quot;&gt;Array&lt;&#x2F;span&gt;[Player] &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; [],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;) &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; void:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; p_name
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    goalkeeper &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; p_goalkeeper
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    field_players &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; p_field_players
&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; Let&amp;#39;s instantiate a team with a goalkeeper&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;team_1&lt;&#x2F;span&gt;: Team &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; Team.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Italy&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; Player.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Gianluigi&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Buffon&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; and a copy of it&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;team_2&lt;&#x2F;span&gt;: Team &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; team_1.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;duplicate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;team_2.name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Italy copy&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; True, because both teams are unique and independent resources&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;team_1.name &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;!=&lt;&#x2F;span&gt; team_2.name&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;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;z-source z-gdscript&quot;&gt;team_2.goalkeeper.name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Ganluigi&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; True, because both are named Gianluigi&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;team_1.goalkeeper.name &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;==&lt;&#x2F;span&gt; team_2.goalkeeper.name&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;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;z-source z-gdscript&quot;&gt;team_2.goalkeeper.surname &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Donnarumma&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;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;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;team_1.goalkeeper.surname &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;==&lt;&#x2F;span&gt; team_2.goalkeeper.surname&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; Let&amp;#39;s instantiate a team with a goalkeeper&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;team_1&lt;&#x2F;span&gt;: Team &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; Team.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Italy&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; Player.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Gianluigi&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Buffon&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;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;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;team_2&lt;&#x2F;span&gt;: Team &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; team_1.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;duplicate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;true&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;team_2.name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Italy copy&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; Still true, because both teams are unique and independent resources&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;team_1.name &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;!=&lt;&#x2F;span&gt; team_2.name&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;team_2.goalkeeper.name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Gianluigi&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; True, because both still are named Gianluigi&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;team_1.goalkeeper.name &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;==&lt;&#x2F;span&gt; team_2.goalkeeper.name&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;team_2.goalkeeper.surname &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Donnarumma&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;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;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;team_1.goalkeeper.surname &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;!=&lt;&#x2F;span&gt; team_2.goalkeeper.surname&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; Lets create once again two players&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;goalkeeper&lt;&#x2F;span&gt;: Player &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; Player.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Gianluigi&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Buffon&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;player_1&lt;&#x2F;span&gt;: Player &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; Player.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Paolo&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Maldini&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;player_2&lt;&#x2F;span&gt;: Player &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; Player.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Alessandro&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Del Piero&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; and a team with the two players&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;team_1&lt;&#x2F;span&gt;: Team &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; Team.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Italy&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; goalkeeper&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; [player_1&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; player_2]&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;team_2&lt;&#x2F;span&gt;: Team &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; team_1.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;duplicate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;true&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;team_2.name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Italy copy&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; lets change a players name&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;team_2.players[&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;0&lt;&#x2F;span&gt;].name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Daniele&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; True&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;team_1.surname &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;!=&lt;&#x2F;span&gt; team_2.surname&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; True, because both player arrays still are the same resource&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;team_1.players[&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;0&lt;&#x2F;span&gt;].name &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;==&lt;&#x2F;span&gt; team_2.players[&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;0&lt;&#x2F;span&gt;].name&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;duplicate_deep&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-support z-class z-gdscript&quot;&gt;Team&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;copy&lt;&#x2F;span&gt;: Team &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;duplicate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;true&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	copy.players &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; []
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;for&lt;&#x2F;span&gt; player: Player &lt;span class=&quot;z-keyword z-operator z-logical z-gdscript&quot;&gt;in&lt;&#x2F;span&gt; field_players:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		copy.players.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;append&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;player.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;duplicate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;true&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;return&lt;&#x2F;span&gt; copy
&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;team_deep&lt;&#x2F;span&gt;: Team &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; team_1.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;duplicate_deep&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;team_deep.name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Italy copy&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; lets change a players surname&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;team_deep.players[&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;0&lt;&#x2F;span&gt;].name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Daniele&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; True&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;team_1.surname &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;!=&lt;&#x2F;span&gt; team_deep.surname&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; True, because both players are unique resources&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;assert&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;team_1.players[&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;0&lt;&#x2F;span&gt;].name &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;!=&lt;&#x2F;span&gt; team_deep.players[&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;0&lt;&#x2F;span&gt;].name&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; paths to check for project.godot file
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;paths_to_check&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;..&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;is_godot_project&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;false&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;godot_project_path&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;cwd&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;getcwd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; iterate over paths and check
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-loop z-lua&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;value&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-lua&quot;&gt;in&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;pairs&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;paths_to_check&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-lua&quot;&gt;do&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;uv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;fs_stat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;cwd&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-concatenation z-lua&quot;&gt;..&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;value&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-concatenation z-lua&quot;&gt;..&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;project.godot&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;is_godot_project&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;godot_project_path&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;cwd&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-concatenation z-lua&quot;&gt;..&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;value&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-break z-lua&quot;&gt;break&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; check if server is already running in godot project path
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;is_server_running&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;uv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;fs_stat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;godot_project_path&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-concatenation z-lua&quot;&gt;..&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;server.pipe&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; start server, if not already running
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;is_godot_project&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-lua&quot;&gt;and&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-lua&quot;&gt;not&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;is_server_running&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;serverstart&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;godot_project_path&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-concatenation z-lua&quot;&gt;..&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;server.pipe&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;--server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;project&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;server.pipe&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;remote-send&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&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;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&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&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&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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt;-@brief
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt;-
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt;- https:&#x2F;&#x2F;github.com&#x2F;godotengine&#x2F;godot
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt;-
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt;- Language server for GDScript, used by Godot Engine.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;port&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-constant z-builtin z-lua&quot;&gt;os&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;getenv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;GDScript_Port&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-lua&quot;&gt;or&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;6005&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;cmd&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;lsp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;rpc&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;connect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;127.0.0.1&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;tonumber&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt;-@type vim.lsp.Config
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-return z-lua&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;filetypes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;gd&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;gdscript&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;gdscript3&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;root_markers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;project.godot&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;.git&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;lsp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;gdscript&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;lsp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;enable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;gdscript&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;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&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&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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; Installation
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;neovim&#x2F;nvim-lspconfig&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; Setup
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;lspconfig&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;require&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;lspconfig&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; godot lsp
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;is_godot_project&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; setup lsp
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;lspconfig&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;gdscript&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&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&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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; Installation
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;nvim-treesitter&#x2F;nvim-treesitter&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-meta z-brackets z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-begin z-lua&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;do&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-end z-lua&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;:TSUpdate&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; Setup
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;require&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;nvim-treesitter.configs&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;ensure_installed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;gdscript&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;godot_resource&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;gdshader&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;highlight&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;enable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; disable auto install of languages when opening files
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;auto_install&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; disable for files bigger than 100 KB
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-lua&quot;&gt;disable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-lua&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function z-lua&quot;&gt;lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-function z-lua&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;max_filesize&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-lua&quot;&gt;100&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-lua&quot;&gt;*&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-lua&quot;&gt;1024&lt;&#x2F;span&gt; &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; 100 KB
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;stats&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;pcall&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;loop&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;fs_stat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_buf_get_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;ok&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-lua&quot;&gt;and&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;stats&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-lua&quot;&gt;and&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;stats&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;size&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-lua&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;max_filesize&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-return z-lua&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;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&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&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Hello&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;breakpoint&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;world!&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; define functions only for Godot projects
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;is_godot_project&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; write breakpoint to new line
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;GodotBreakpoint&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-lua&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;normal! obreakpoint&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;write&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;keymap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;n&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&amp;lt;leader&amp;gt;b&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;:GodotBreakpoint&amp;lt;CR&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; delete all breakpoints in current file
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;GodotDeleteBreakpoints&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-lua&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;g&#x2F;breakpoint&#x2F;d&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;keymap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;n&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&amp;lt;leader&amp;gt;BD&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;:GodotDeleteBreakpoints&amp;lt;CR&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; search all breakpoints in project
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;GodotFindBreakpoints&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-lua&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;:grep breakpoint | copen&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;keymap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;n&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&amp;lt;leader&amp;gt;BF&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;:GodotFindBreakpoints&amp;lt;CR&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; append &amp;quot;# TRANSLATORS: &amp;quot; to current line
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;GodotTranslators&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-lua&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function z-lua&quot;&gt;opts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;normal! A # TRANSLATORS: &lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&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&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&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&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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ----------------------
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; vim-plug plugin-manager
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ----------------------
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;Plug&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brackets z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-begin z-lua&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;plug#&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-end z-lua&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;plug#begin&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;nvim-treesitter&#x2F;nvim-treesitter&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-meta z-brackets z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-begin z-lua&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;do&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-end z-lua&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;:TSUpdate&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;neovim&#x2F;nvim-lspconfig&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;plug#end&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ----------------------
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; lsp
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ----------------------
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;lspconfig&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;require&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;lspconfig&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;lspconfig&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;gdscript&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ----------------------
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; treesitter
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; -- ----------------------
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;require&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;nvim-treesitter.configs&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;ensure_installed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;gdscript&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;godot_resource&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;gdshader&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;highlight&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;enable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; disable auto install of languages when opening files
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;auto_install&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; disable for files bigger than 100 KB
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-lua&quot;&gt;disable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-lua&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function z-lua&quot;&gt;lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-function z-lua&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;max_filesize&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-lua&quot;&gt;100&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-lua&quot;&gt;*&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-lua&quot;&gt;1024&lt;&#x2F;span&gt; &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; 100 KB
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-storage z-modifier z-lua&quot;&gt;local&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;stats&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-lua&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;pcall&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;loop&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;fs_stat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_buf_get_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;ok&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-lua&quot;&gt;and&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;stats&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-lua&quot;&gt;and&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;stats&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;size&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-lua&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;max_filesize&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-return z-lua&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ----------------------
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; Godot debug config
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ----------------------
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; write breakpoint to new line
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;GodotBreakpoint&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-lua&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;normal! obreakpoint&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;write&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;keymap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;n&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&amp;lt;leader&amp;gt;b&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;:GodotBreakpoint&amp;lt;CR&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; delete all breakpoints in current file
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;GodotDeleteBreakpoints&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-lua&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;g&#x2F;breakpoint&#x2F;d&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;keymap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;n&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&amp;lt;leader&amp;gt;BD&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;:GodotDeleteBreakpoints&amp;lt;CR&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; search all breakpoints in project
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;GodotFindBreakpoints&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-lua&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;:grep breakpoint | copen&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;keymap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;n&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&amp;lt;leader&amp;gt;BF&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;:GodotFindBreakpoints&amp;lt;CR&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;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&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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;is_godot_project&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ignore *.uid files introduced in godot 4.4
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ignore server.pipe file
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;    &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;let NERDTreeIgnore = [&amp;quot;&lt;span class=&quot;z-constant z-character z-escape z-lua&quot;&gt;\\&lt;&#x2F;span&gt;.uid$&amp;quot;, &amp;quot;server.pipe&amp;quot;]&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&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&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 data-lang=&quot;lua&quot; class=&quot;language-lua z-code&quot;&gt;&lt;code class=&quot;language-lua&quot; data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ----------------------
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; oil
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ----------------------
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-lua&quot;&gt;require&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;oil&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;view_options&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-lua&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-key z-lua&quot;&gt;show_hidden&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-lua&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-lua&quot;&gt;is_always_hidden&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-lua&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt; &lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-lua&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function z-lua&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-function z-lua&quot;&gt;bufnr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;            &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; for godot projects ignore *.uid files
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;is_godot_project&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;                &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ignore *.uid files introduced in godot 4.4
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;                &lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-lua&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property z-lua&quot;&gt;&lt;span class=&quot;z-variable z-function z-lua&quot;&gt;endswith&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-lua&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-lua&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-lua&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;.uid&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;                    &lt;span class=&quot;z-keyword z-control z-return z-lua&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;                &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;                &lt;span class=&quot;z-comment z-line z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-lua&quot;&gt;--&lt;&#x2F;span&gt; ignore server.pipe file
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;                &lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-lua&quot;&gt;name&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-lua&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;server.pipe&lt;span class=&quot;z-punctuation z-definition z-string z-end z-lua&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;                    &lt;span class=&quot;z-keyword z-control z-return z-lua&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;                &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;            &lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-lua&quot;&gt;else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;                &lt;span class=&quot;z-keyword z-control z-return z-lua&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-lua&quot;&gt;false&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;            &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function z-lua&quot;&gt;&lt;span class=&quot;z-meta z-block z-lua&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-end z-lua&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-field z-lua&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-lua&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-lua&quot;&gt;&lt;span class=&quot;z-meta z-group z-lua&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-lua&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-lua&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-lua&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; This long path&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-keyword z-other z-onready z-gdscript&quot;&gt;onready&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;healt_label&lt;&#x2F;span&gt;: Label &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; $MarginContainer&lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;&#x2F;&lt;&#x2F;span&gt;HBoxContainer&lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;&#x2F;&lt;&#x2F;span&gt;VBoxContainer&lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;&#x2F;&lt;&#x2F;span&gt;HealthLabel
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; simply becomes&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-keyword z-other z-onready z-gdscript&quot;&gt;onready&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;healt_label&lt;&#x2F;span&gt;: Label &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;%&lt;&#x2F;span&gt;HealthLabel
&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&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&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&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&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&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&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Control&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-keyword z-other z-onready z-gdscript&quot;&gt;onready&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;animation_player&lt;&#x2F;span&gt;: AnimationPlayer &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;%&lt;&#x2F;span&gt;AnimationPlayer
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	theme &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; ThemeUtil.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_active_theme&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	animation_player.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;play&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Teaser&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install 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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install 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&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install 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&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install 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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install tlp&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; start it&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;tlp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Suspend the system on 5% or lower&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;SUBSYSTEM&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;=&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;power_supply&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;ATTR{status}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;=&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Discharging&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;ATTR{capacity}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;=&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;[0-5]&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;usr&#x2F;bin&#x2F;systemctl suspend&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&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&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&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install 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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;# for light and systemctl shutdown, suspend, reboot&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt; &#x2F;etc&#x2F;sudoers&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;%dulvui ALL=(root) NOPASSWD: &#x2F;usr&#x2F;bin&#x2F;light,&#x2F;usr&#x2F;bin&#x2F;systemctl&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; more bright&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;light&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;A&lt;&#x2F;span&gt; 5&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; less bright&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;light&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;U&lt;&#x2F;span&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;systemctl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; poweroff&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;systemctl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; suspend&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;systemctl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; as root&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;vim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &#x2F;etc&#x2F;systemd&#x2F;logind.conf&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; change following values&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;HandlePowerKey&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;ignore&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;HandlePowerKeyLongPress&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;poweroff&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; restart logind or reboot&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;systemctl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; restart 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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; audio&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install pipewire&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install wireplumber&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install pipewire-alsa&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install pipewire-audio &lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install pipewire-audio-client-libraries&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install pipewire-bin&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install pipewire-jack&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install pipewire-pulse&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; bluetooth&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install bluez&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; gui for pairing&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install blueman&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; for a2dp and other bluetooth profiles&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install 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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Sway autostart&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-if z-shell&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-test z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;z&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;WAYLAND_DISPLAY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-test z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-and z-shell&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-test z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;XDG_VTNR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;eq&lt;&#x2F;span&gt; 1 &lt;span class=&quot;z-support z-function z-test z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-then z-shell&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-shell&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;MOZ_ENABLE_WAYLAND&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-shell&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;XDG_SESSION_TYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;wayland&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-shell&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;XDG_CURRENT_DESKTOP&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;sway&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-exec z-shell&quot;&gt;exec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; sway&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-end z-shell&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install xdg-desktop-portal&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install 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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-exec z-shell&quot;&gt;exec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &#x2F;usr&#x2F;libexec&#x2F;xdg-desktop-portal -r&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-exec z-shell&quot;&gt;exec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; first, install build deps&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;apt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; install&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;y&lt;&#x2F;span&gt; ninja-build gettext cmake unzip curl build-essential&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; clone neovim&amp;#39;s repo&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; clone https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-cd z-shell&quot;&gt;cd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; check out stable tag, or specific version you prefer&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; checkout stable&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; build neovim&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;make&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; CMAKE_BUILD_TYPE=RelWithDebInfo&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-cd z-shell&quot;&gt;cd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; build&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-and z-shell&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;cpack&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;G&lt;&#x2F;span&gt; DEB&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; install it, as root&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;dpkg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;i&lt;&#x2F;span&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; switch back to master&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; checkout master&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; pull&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; fetch&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;all&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; check out stable tag, or specific version you prefer&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; checkout 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&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;mdir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;p&lt;&#x2F;span&gt; .config&#x2F;nvim&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;touch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&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&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&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&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;your.dom.ain&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;        reverse_proxy &#x2F;ws&#x2F;&lt;span class=&quot;z-keyword z-operator z-regexp z-quantifier z-shell&quot;&gt;*&lt;&#x2F;span&gt; localhost:8000
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;        handle &#x2F;ws&#x2F;&lt;span class=&quot;z-keyword z-operator z-regexp z-quantifier z-shell&quot;&gt;*&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;                reverse_proxy localhost:8000
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;        &lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-const z-gdscript&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;HOST&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;wss:&#x2F;&#x2F;your.dom.ain&#x2F;ws&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; dynamic&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;a&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;hello&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; automatic type guess&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;b&lt;&#x2F;span&gt; :&lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;hello&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; static typing&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;c&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;hello&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;class_name StaticClass
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Node&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;alice&lt;&#x2F;span&gt;: &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Node2D&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;static_class&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; StaticClass.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    static_class.alice &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;Error: Invalid set index &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;alice&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;on base: &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;Node (StaticClass)&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; with value of type &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;int&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Node2D&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;static_class&lt;&#x2F;span&gt;:StaticClass &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; StaticClass.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    static_class.alice &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;Cannot assign a value of type &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;int&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; as &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;String&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Node2D&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;static_class&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; StaticClass.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    static_class.bob &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;Error: Invalid set index &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;bob&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;on base: &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;Node (StaticClass)&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; with value of type &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;int&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Node2D&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;static_class&lt;&#x2F;span&gt;: StaticClass &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; StaticClass.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    static_class.bob &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;The property &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;bob&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-gdscript&quot;&gt;is&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-gdscript&quot;&gt;not&lt;&#x2F;span&gt; present on the inferred type &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;StaticClass&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;but may be present on a subtype&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;. &lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;Warning treated as error.&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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&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&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&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;app-id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;org.simondalvai.ball2box&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;runtime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;org.freedesktop.Platform&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;runtime-version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;23.08&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;sdk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;org.freedesktop.Sdk&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;base&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;org.godotengine.godot.BaseApp&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; Godot version
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;base-version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;3.5-23.08&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;godot-runner&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;finish-args&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;--share=ipc&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;--socket=x11&lt;&#x2F;span&gt; &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; &amp;lt;-- Godot needs X11
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;--socket=pulseaudio&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;--device=dri&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;modules&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Ball2Box&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;buildsystem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;simple&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;build-commands&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; The game itself
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;install Ball2Box.pck &#x2F;app&#x2F;bin&#x2F;godot-runner.pck&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; Metadata and a .desktop file
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;install -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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;install -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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; Icons
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;install -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;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;sources&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; The game is pulled from GitHub
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;archive&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;strip-components&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;0&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;url&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;https:&#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;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;sha256&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;971b4a47bda0aa3f0bc6e1766b61eb848d0e10156505fef1f66531ac375bd5d4&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;file&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;url&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;https:&#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;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;sha256&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;6a6d1d14649730dc3c61ce8c62baed9d2b8f2c71c801b1a8420275361bdff2e1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;file&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;url&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;https:&#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;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;sha256&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;c4aa1c9d9f3091c0be44269f591589bf5fc181c172a06f6882981345331f9552&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;file&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;icon-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&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&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 data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-preprocessor z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-xml&quot;&gt;xml&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;encoding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;UTF-8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;?&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;component&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;desktop-application&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;org.simondalvai.ball2box&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Ball2Box&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;developer_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Simon Dalvai&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;developer_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;launchable&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;desktop-id&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;org.simondalvai.ball2box.desktop&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;launchable&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;project_license&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;AGPL-3.0-or-later&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;project_license&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;metadata_license&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;CC0-1.0&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;metadata_license&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;summary&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Shoot the ball into the red box&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;summary&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;url&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;homepage&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;ball2box&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;url&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;bugtracker&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;issues&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;url&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;donation&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;https:&#x2F;&#x2F;simondalvai.org&#x2F;donate&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;url&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;vcs-browser&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Can you get all three stars on all levels?
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;120+ levels and more coming soon...&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;20+ different styled balls to collect&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Privacy friendly&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Offline game&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Created with Godot Engine 3&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;branding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;color&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;primary&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;scheme_preference&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;light&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;#fdf6e3&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;color&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;color&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;primary&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;scheme_preference&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;dark&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;#002b36&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;color&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;branding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;screenshots&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;screenshot&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;default&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&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;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&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;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&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;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&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;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;screenshots&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;content_rating&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;oars-1.1&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;releases&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;release&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;4.1.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;2024-02-15&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;          &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;levels functionality&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;          &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;user interface refactoring&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;li&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;      &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;releases&#x2F;tag&#x2F;v4.1.0&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;release&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;  &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;releases&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;component&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&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&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&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 data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;!&#x2F;usr&#x2F;bin&#x2F;env xdg-open&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;[Desktop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; Entry]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;Ball2Box&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;GenericName&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;Ball2Box&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;Comment&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;Shoot&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;the&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; ball into the red box!&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;Exec&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;godot-runner&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;Icon&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;org.simondalvai.ball2box&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;Application&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;Categories&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;Game&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; RigidBody&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;class_name Ball
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; ...omitted code&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;reset&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    mode &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; RigidBody.MODE_STATIC
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    translation &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; initial_position
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    linear_velocity &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector3&lt;&#x2F;span&gt;.ZERO
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    angular_velocity &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector3&lt;&#x2F;span&gt;.ZERO
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    rotation &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector3&lt;&#x2F;span&gt;.ZERO
&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 data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Called&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; during physics processing, allowing you to read and safely modify the simulation state for the 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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; RigidBody&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;class_name Ball
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;do_teleport&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;bool&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;false&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;do_reset&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;bool&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;false&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;do_static&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;bool&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;false&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;initial_position&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Transform&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;next_transform&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Transform&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;teleport&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;p_transform&lt;&#x2F;span&gt;:&lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;Transform&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	next_transform &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; p_transform
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	do_teleport &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;teleport_to_initial&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	do_reset &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_integrate_forces&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;state&lt;&#x2F;span&gt;:&lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;PhysicsDirectBodyState&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; change the mode to static on the next iteration&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; otherwise ball doesn&amp;#39;t move to new position&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;if&lt;&#x2F;span&gt; do_static:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		do_static &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;false&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		mode &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; RigidBody.MODE_STATIC
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;if&lt;&#x2F;span&gt; do_teleport:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		state.transform &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; next_transform
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		do_teleport &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;false&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;if&lt;&#x2F;span&gt; do_reset:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		state.transform &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; initial_position
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		state.angular_velocity &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector3&lt;&#x2F;span&gt;.ZERO
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		state.linear_velocity &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector3&lt;&#x2F;span&gt;.ZERO
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		rotation &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector3&lt;&#x2F;span&gt;.ZERO
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		do_reset &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;false&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		do_static &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_on_Portal1_ball_entered&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;ball&lt;&#x2F;span&gt;:&lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;Ball&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	ball.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;teleport&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;portal2.transform&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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&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&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&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&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&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 data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;openssl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; genrsa&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;out&lt;&#x2F;span&gt; distribution.key 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 data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;openssl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; req&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;key&lt;&#x2F;span&gt; distribution.key&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;out&lt;&#x2F;span&gt; distribution.csr&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;subj&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&#x2F;emailAddress=info@simondalvai.org, CN=Simon Dalvai, C=IT&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&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 data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;openssl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; x509&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;inform&lt;&#x2F;span&gt; der&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;in&lt;&#x2F;span&gt; distribution.cer&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;out&lt;&#x2F;span&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&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 data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;wget&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&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;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;openssl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; x509&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;in&lt;&#x2F;span&gt; AppleWWDRCAG4.cer&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;inform&lt;&#x2F;span&gt; DER&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;out&lt;&#x2F;span&gt; AppleWWDRCAG4.pem&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;outform&lt;&#x2F;span&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&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 data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;openssl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; pkcs12&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;legacy&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;out&lt;&#x2F;span&gt; distribution.p12&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;inkey&lt;&#x2F;span&gt; distribution.key&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;in&lt;&#x2F;span&gt; distribution.pem&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;certfile&lt;&#x2F;span&gt; AppleWWDRCAG4.pem &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 data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;base64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; distribution.p12&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;w&lt;&#x2F;span&gt; 0 &lt;span class=&quot;z-keyword z-operator z-assignment z-redirection z-shell&quot;&gt;&amp;gt;&lt;&#x2F;span&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 data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;n&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;BUILD_CERTIFICATE_BASE64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-pipe z-shell&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;base64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;decode&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;o&lt;&#x2F;span&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&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&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;class_name MyResource
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Resource&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-signal z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-signal z-gdscript&quot;&gt;signal&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-signal z-gdscript&quot;&gt;such_signal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-enum z-gdscript&quot;&gt;enum&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-gdscript&quot;&gt;SuchEnum&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-gdscript&quot;&gt;{&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-entity z-name z-enum z-gdscript&quot;&gt;Hello&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-entity z-name z-enum z-gdscript&quot;&gt;Custom&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-entity z-name z-enum z-gdscript&quot;&gt;Resources&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;span class=&quot;z-punctuation z-section z-mapping z-end z-gdscript&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;name&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;id&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;int&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;0&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;values&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-container z-gdscript&quot;&gt;Array&lt;&#x2F;span&gt;[&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;int&lt;&#x2F;span&gt;]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;enumValue&lt;&#x2F;span&gt;:SuchEnum
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;get_sum&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;sum&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;int&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;0&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;for&lt;&#x2F;span&gt; value &lt;span class=&quot;z-keyword z-operator z-logical z-gdscript&quot;&gt;in&lt;&#x2F;span&gt; values:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;        sum &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+=&lt;&#x2F;span&gt; value
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;return&lt;&#x2F;span&gt; sum
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;special_effect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arrow z-forward z-gdscript&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-return-type&quot;&gt; &lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;void&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;randi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;%&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;10&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1&lt;&#x2F;span&gt;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;        such_signal.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;emit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; create variable&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;my_resource&lt;&#x2F;span&gt;:MyResource &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; MyResource.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; assign values&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;my_resource.name &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Hello Resources&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;my_resource.values &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; [&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;0&lt;&#x2F;span&gt;, &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;3&lt;&#x2F;span&gt;, &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;12&lt;&#x2F;span&gt;]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; save it&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;ResourceSaver.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;save&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;my_resource&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;my_resource.tres&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; load it&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;my_resource_from_disk&lt;&#x2F;span&gt;:MyResource &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;load&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;my_resource.tres&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; prints &amp;quot;Hello Resources&amp;quot;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;my_resource_from_disk.name&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; prints &amp;quot;15&amp;quot;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;my_resource_from_disk.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;sum&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; team.gd&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Resource&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;class_name Team
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;name&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;line_up&lt;&#x2F;span&gt;:LineUp
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;prestige&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;int&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;budget&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;int&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;salary_budget&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;int&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;players&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-container z-gdscript&quot;&gt;Array&lt;&#x2F;span&gt;[Player]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; ...code goes on here&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; player.gd&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;class_name Player
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Resource&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;id&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;int&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;price&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;int&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;name&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;surname&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-basic z-gdscript&quot;&gt;String&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;@&lt;span class=&quot;z-storage z-modifier z-static z-gdscript&quot;&gt;export&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;birth_date&lt;&#x2F;span&gt;:&lt;span class=&quot;z-storage z-type z-container z-gdscript&quot;&gt;Dictionary&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;itch.io upload&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; define what triggers the action
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-constant z-language z-boolean z-yaml&quot;&gt;on&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;push&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;paths&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;version-android&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;version-ios&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.github&#x2F;workflows&#x2F;upload-itchio.yml&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; the directory where your game is
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;WORKING_DIRECTORY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;game&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;jobs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;deploy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; only run action, if pushed on prod branch
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; change or remove according to your needs
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;if&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;github.ref == &amp;#39;refs&#x2F;heads&#x2F;prod&amp;#39;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;runs-on&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;ubuntu-20.04&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;steps&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Checkout source code&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;uses&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;actions&#x2F;checkout@v3&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; change or remove according to your needs
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Delete iOS icons&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;rm -rf $WORKING_DIRECTORY&#x2F;AppIcons&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; change or remove according to your needs
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Create export directory&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;mkdir html5&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; exports the game in html mode
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Godot HTML5 export&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;uses&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;dulvui&#x2F;godot-html-export@v0.0.2&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;working-directory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;$WORKING_DIRECTORY&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&gt; uploads to itch.io
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-comment z-line z-number-sign z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-line z-number-sign z-yaml&quot;&gt;#&lt;&#x2F;span&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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Upload to itch.io&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;uses&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;dulvui&#x2F;itchio-butler-upload@v0.0.1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;working-directory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;html5&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;api-key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;${{ secrets.ITCHIO_API_KEY }}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;user&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;simondalvai&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;game&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;ball2box&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;channel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;html5&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&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&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&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&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&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&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&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&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&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&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&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&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Categories&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Games&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;License&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;AGPL-3.0-or-later&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;AuthorName&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Simon Dalvai&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;AuthorEmail&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;info@simondalvai.org&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;AuthorWebSite&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;https:&#x2F;&#x2F;simondalvai.org&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;WebSite&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;ball2box&#x2F;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;SourceCode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;IssueTracker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;issues&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Donate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;https:&#x2F;&#x2F;simondalvai.org&#x2F;donate&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Ball2Box&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;AutoName&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Ball2Box&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;RepoType&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;git&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Repo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box.git&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;Builds&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;versionName&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-decimal z-yaml&quot;&gt;2&lt;span class=&quot;z-punctuation z-separator z-decimal z-yaml&quot;&gt;.&lt;&#x2F;span&gt;2.6&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;versionCode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;44&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;commit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;a9ec9a5f025542c27196a0f5b3507a652e05e907&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;apt-get update&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;apt-get install -y clang gettext pkg-config scons&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;output&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;game&#x2F;Ball2Box.apk&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;srclibs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Godot@6fed1ffa313c6760fa88b368ae580378daaef0f0&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;prebuild&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;mv fdroid&#x2F;export_presets.cfg game&#x2F;export_presets.cfg&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;sed -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;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;export HOME=$PWD&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;cp -R $$Godot$$ godot&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;keytool -genkey -v -keystore debug.keystore -storepass android -alias androiddebugkey&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;-keypass 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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;mkdir -p .&#x2F;.config&#x2F;godot&#x2F;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;export 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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;export 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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;echo &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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;echo &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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;echo $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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;echo $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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;echo &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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;echo &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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;cd godot&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;scons -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;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;profile=fdroid&#x2F;godot-build-options.py&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;export ANDROID_NDK_ROOT=$$NDK$$&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;scons -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;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;android_arch=armv7 profile=fdroid&#x2F;godot-build-options.py&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;scons -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;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;android_arch=arm64v8 profile=fdroid&#x2F;godot-build-options.py&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;pushd platform&#x2F;android&#x2F;java&#x2F;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;gradle generateGodotTemplates&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;popd&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;cd ..&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;mkdir -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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;echo &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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;cp 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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&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;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;find . -iname &amp;quot;*.apk&amp;quot;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;echo &amp;quot;build end&amp;quot;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;ndk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;r23c&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;AutoUpdateMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Version&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;UpdateCheckMode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Tags&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;UpdateCheckData&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;fdroid&#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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;CurrentVersion&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-float z-decimal z-yaml&quot;&gt;2&lt;span class=&quot;z-punctuation z-separator z-decimal z-yaml&quot;&gt;.&lt;&#x2F;span&gt;2.6&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;CurrentVersionCode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;44&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</description>
      </item>
      <item>
          <title>Donate</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;I hope to fund my development through the sales of my games on&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&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&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;li&gt;other platforms will follow soon...&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Don&#x27;t forget to leave a honest &lt;strong&gt;review&lt;&#x2F;strong&gt;, that helps me a lot.&lt;&#x2F;p&gt;
&lt;p&gt;You also can donate on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;liberapay.com&#x2F;dulvui&quot;&gt;Liberapay&lt;&#x2F;a&gt;, if you prefer that.&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 data-lang=&quot;css&quot; class=&quot;language-css z-code&quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-media z-css&quot;&gt;&lt;span class=&quot;z-keyword z-control z-at-rule z-media z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-keyword z-css&quot;&gt;@&lt;&#x2F;span&gt;media&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;prefers-&lt;span class=&quot;z-support z-type z-property-name z-media z-css&quot;&gt;color&lt;&#x2F;span&gt;-scheme: dark&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;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 data-lang=&quot;css&quot; class=&quot;language-css z-code&quot;&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-media z-css&quot;&gt;&lt;span class=&quot;z-keyword z-control z-at-rule z-media z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-keyword z-css&quot;&gt;@&lt;&#x2F;span&gt;media&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;prefers-&lt;span class=&quot;z-support z-type z-property-name z-media z-css&quot;&gt;color&lt;&#x2F;span&gt;-scheme: light&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;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 data-lang=&quot;scss&quot; class=&quot;language-scss z-code&quot;&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;&lt;span class=&quot;z-variable z-declaration z-sass&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-sass&quot;&gt;$&lt;&#x2F;span&gt;background-color-light&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;span class=&quot;z-constant z-other z-color z-rgb-value z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-constant z-css&quot;&gt;#&lt;&#x2F;span&gt;FDF6E3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;&lt;span class=&quot;z-variable z-declaration z-sass&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-sass&quot;&gt;$&lt;&#x2F;span&gt;background-color-dark&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;span class=&quot;z-constant z-other z-color z-rgb-value z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-constant z-css&quot;&gt;#&lt;&#x2F;span&gt;002b36&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;&lt;span class=&quot;z-variable z-declaration z-sass&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-sass&quot;&gt;$&lt;&#x2F;span&gt;font-color-light&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;span class=&quot;z-variable z-other z-sass&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-sass&quot;&gt;$&lt;&#x2F;span&gt;background-color-dark&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;&lt;span class=&quot;z-variable z-declaration z-sass&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-sass&quot;&gt;$&lt;&#x2F;span&gt;font-color-dark&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;span class=&quot;z-variable z-other z-sass&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-sass&quot;&gt;$&lt;&#x2F;span&gt;background-color-light&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;&lt;span class=&quot;z-meta z-selector z-css&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-css&quot;&gt;body&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-begin z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;background-color&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;span class=&quot;z-variable z-other z-sass&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-sass&quot;&gt;$&lt;&#x2F;span&gt;background-color-light&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;    &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;color&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;span class=&quot;z-variable z-other z-sass&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-sass&quot;&gt;$&lt;&#x2F;span&gt;font-color-light&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;&lt;span class=&quot;z-meta z-at-rule z-media z-css&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-at-rule z-media z-css&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-keyword z-css&quot;&gt;@&lt;&#x2F;span&gt;media&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-group z-begin z-css&quot;&gt;(&lt;&#x2F;span&gt;prefers&lt;span class=&quot;z-keyword z-operator z-sass&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-media z-css&quot;&gt;color&lt;&#x2F;span&gt;-scheme&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt; dark&lt;span class=&quot;z-punctuation z-definition z-group z-end z-css&quot;&gt;)&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-begin z-css&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;        &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;background-color&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;span class=&quot;z-variable z-other z-sass&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-sass&quot;&gt;$&lt;&#x2F;span&gt;background-color-dark&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;        &lt;span class=&quot;z-meta z-property-name z-css&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-css&quot;&gt;color&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-css&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value z-css&quot;&gt; &lt;span class=&quot;z-variable z-other z-sass&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-sass&quot;&gt;$&lt;&#x2F;span&gt;font-color-dark&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rule z-css&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-property-list z-end z-css&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-scss&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-property-list z-end z-css&quot;&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&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&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&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&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&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-const z-gdscript&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;resolutions&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-gdscript&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;	 &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Android&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1080&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1920&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;	 &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;iPhone5.5&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1242&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2208&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;	 &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;iPhone6.5&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1284&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2778&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;	 &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;iPhone6.7&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1290&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2796&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;	 &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;iPad12.9&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2048&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2732&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-end z-gdscript&quot;&gt;}&lt;&#x2F;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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-const z-gdscript&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;scenes&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; [
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level1.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level10.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level11.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level13.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level24.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level70.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level99.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level105.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_change_scene&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;scene_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;if&lt;&#x2F;span&gt; scene &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;!=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;null&lt;&#x2F;span&gt;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;remove_child&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;scene&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		scene.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;queue_free&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;next_scene&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;load&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;scene_path&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	scene &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; next_scene.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;instance&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;add_child&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;scene&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; hide menu&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	scene.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;UI&#x2F;Menu&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;hide&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;OS.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;set_window_size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;resolutions.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;resolution&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;image&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_viewport&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_texture&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_rect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;fullscreen&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;image.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;flip_y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;image.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;save_png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;..&#x2F;screenshots&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+&lt;&#x2F;span&gt; resolution &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;str&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;scene_counter&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.png&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&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 data-lang=&quot;gd&quot; class=&quot;language-gd z-code&quot;&gt;&lt;code class=&quot;language-gd&quot; data-lang=&quot;gd&quot;&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-keyword z-other z-gdscript&quot;&gt;extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-inherited-class z-gdscript&quot;&gt; Spatial&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-const z-gdscript&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;resolutions&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-gdscript&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;	 &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Android&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1080&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1920&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;	 &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;iPhone5.5&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1242&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2208&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;	 &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;iPhone6.5&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1284&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2778&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;	 &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;iPhone6.7&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1290&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2796&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-gdscript&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;	 &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;iPad12.9&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-gdscript&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Vector2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2048&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2732&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-end z-gdscript&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-const z-gdscript&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;scenes&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; [
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level1.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level10.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level11.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level13.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level24.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level70.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level99.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level105.tscn&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;scene&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;scene_counter&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;for&lt;&#x2F;span&gt; scene &lt;span class=&quot;z-keyword z-operator z-logical z-gdscript&quot;&gt;in&lt;&#x2F;span&gt; scenes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;_change_scene&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;scene&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;for&lt;&#x2F;span&gt; resolution &lt;span class=&quot;z-keyword z-operator z-logical z-gdscript&quot;&gt;in&lt;&#x2F;span&gt; resolutions.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;keys&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			OS.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;set_window_size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;resolutions.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;resolution&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			&lt;span class=&quot;z-keyword z-control z-flow z-yield z-gdscript&quot;&gt;yield&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_tree&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;create_timer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;, &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;timeout&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;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;z-source z-gdscript&quot;&gt;			&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;x&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;resolutions.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;resolution&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.x &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_viewport&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_texture&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.x) &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;y&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;resolutions.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;resolution&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.y &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_viewport&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_texture&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.y) &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;2&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;fullscreen&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-vector z-gdscript&quot;&gt;Rect2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;-&lt;&#x2F;span&gt; x&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;0&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;-&lt;&#x2F;span&gt; y&lt;span class=&quot;z-punctuation z-separator z-arguments z-gdscript&quot;&gt;,&lt;&#x2F;span&gt; resolutions.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;resolution&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.x, resolutions.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;resolution&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.y)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;image&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_viewport&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_texture&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_rect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;fullscreen&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			image.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;flip_y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;			image.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;save_png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;..&#x2F;screenshots&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+&lt;&#x2F;span&gt; resolution &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;str&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;scene_counter&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.png&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		scene_counter &lt;span class=&quot;z-keyword z-operator z-arithmetic z-gdscript&quot;&gt;+=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-gdscript&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_tree&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;quit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-gdscript&quot;&gt;func&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-gdscript&quot;&gt;_change_scene&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-gdscript&quot;&gt;scene_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-gdscript&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-keyword z-control z-flow z-gdscript&quot;&gt;if&lt;&#x2F;span&gt; scene &lt;span class=&quot;z-keyword z-operator z-comparison z-gdscript&quot;&gt;!=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-gdscript&quot;&gt;null&lt;&#x2F;span&gt;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;remove_child&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;scene&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;		scene.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;queue_free&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-storage z-type z-var z-gdscript&quot;&gt;var&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-gdscript&quot;&gt;next_scene&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;load&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;scene_path&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	scene &lt;span class=&quot;z-keyword z-operator z-assignment z-gdscript&quot;&gt;=&lt;&#x2F;span&gt; next_scene.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;instance&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;add_child&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;scene&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	&lt;span class=&quot;z-comment z-line z-number-sign z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-number-sign z-gdscript&quot;&gt;#&lt;&#x2F;span&gt; hide menu&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&quot;&gt;	scene.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;get_node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-gdscript&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;UI&#x2F;Menu&lt;span class=&quot;z-punctuation z-definition z-string z-end z-gdscript&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-meta z-function-call z-gdscript&quot;&gt;&lt;span class=&quot;z-variable z-function z-gdscript&quot;&gt;hide&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-gdscript&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-gdscript&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-gdscript&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-gdscript&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&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&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&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&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Set up JDK 1.8&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;uses&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;actions&#x2F;setup-java@v3&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;distribution&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;temurin&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;java-version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Setup Android SDK&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;uses&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;android-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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Cache Godot files&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;cache-godot&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;uses&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;actions&#x2F;cache@v3&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        ~&#x2F;.local&#x2F;share&#x2F;godot&#x2F;**
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        &#x2F;usr&#x2F;local&#x2F;bin&#x2F;godot
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        ~&#x2F;.config&#x2F;godot&#x2F;**
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;&lt;&#x2F;span&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Download and config Godot Engine headless linux server and templates&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;if&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;steps.cache-godot.outputs.cache-hit != &amp;#39;true&amp;#39;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    mkdir ~&#x2F;.cache
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    mkdir -p ~&#x2F;.config&#x2F;godot
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    unzip Godot_v${{ inputs.godot-version }}-stable_export_templates.tpz
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Set Android SDK path in Godot Editor settings&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;if&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;steps.cache-godot.outputs.cache-hit != &amp;#39;true&amp;#39;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;SETTINGS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        export&#x2F;android&#x2F;shutdown_adb_on_exit = true
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        export&#x2F;android&#x2F;force_system_user = false
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;&lt;&#x2F;span&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;echo $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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Export&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;godot --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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Publish to Play Store&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;uses&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;r0adkll&#x2F;upload-google-play@v1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;serviceAccountJson&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;${{ inputs.service-account-json }}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;packageName&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;${{ inputs.package-name }}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;releaseFiles&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;${{ inputs.release-file }}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;track&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;${{ inputs.release-track }}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;completed&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&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&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&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&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Check is running on mac-os&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;if&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;runner.os != &amp;#39;macos&amp;#39;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;exit 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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Cache Godot files&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;cache-godot&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;uses&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;actions&#x2F;cache@v3&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        ~&#x2F;.local&#x2F;share&#x2F;godot&#x2F;**
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        godot
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        ~&#x2F;.config&#x2F;godot&#x2F;**
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;&lt;&#x2F;span&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&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&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Download and config Godot Engine headless linux server and templates&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;if&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;steps.cache-godot.outputs.cache-hit != &amp;#39;true&amp;#39;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    unzip Godot_v${{ inputs.godot-version }}-stable_export_templates.tpz
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    mkdir -p ~&#x2F;.config&#x2F;godot
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    mv bin&#x2F;godot .
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    .&#x2F;godot -e -q
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Godot iOS export&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Extract Provisioning profile UUID and create PP_UUID env variable&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;echo &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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Force XCode 13.4&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;sudo 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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Resolve package dependencies&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;xcodebuild -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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Build the xarchive&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    set -eo pipefail
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    xcodebuild  clean archive \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        -scheme ${{ inputs.project-name }} \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        -configuration &amp;quot;Release&amp;quot; \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        -sdk iphoneos \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        CODE_SIGN_STYLE=Manual \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        PROVISIONING_PROFILE=$PP_UUID \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Export .ipa&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    set -eo pipefail
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        -exportOptionsPlist exportOptions.plist \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        -exportPath $PWD&#x2F;build \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        -allowProvisioningUpdates \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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 data-lang=&quot;yml&quot; class=&quot;language-yml z-code&quot;&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Publish the App on TestFlight&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;bash&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;if&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;success()&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;APPLEID_USERNAME&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;${{ inputs.apple-id-username }}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;APPLEID_PASSWORD&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;${{ inputs.apple-id-password }}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    xcrun altool \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        --upload-app \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        -t ios \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        -f $PWD&#x2F;build&#x2F;*.ipa \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        -u &amp;quot;${{ inputs.apple-id-username }}&amp;quot; \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;        -p &amp;quot;${{ inputs.apple-id-password }}&amp;quot; \
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&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&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&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>
