Another night in the X4 sandbox: https://www.youtube.com/watch?v=665hXLKSfek / https://tube.tchncs.de/w/pHFP8jZf7PYLyLZSARZQ4T

This is heavily distilled early gameplay of X4: Foundations, where I started another play-through slowly expanding my little empire with trade, side missions, station building, border patrol (loosing the the “Misfit”, my good old starter-ship), a surprise Xenon attack on a station where I was just for shopping and eventually good old fashioned piracy with unexpected guest appearance of some Kha’ak trying to crash the party.

01:11 Setting up trade routes aboard The Law Abiding Windrunner
02:20 Switching over to the Misfit
03:05 Witnessing the death of a trading station (while escorting my own ships to safety)
03:50 Patrolling for money (and looting stuff)
05:48 Repairing satellites (in EVA suit)
07:32 Docking at the impressive Teladi ring station for shopping
08:45 Surprise attack on the ring station by a Xenon K (and it’s demise)
14:32 Extending my own station and buying more mining ships
11:26 Switching over to my frigate for border patrol (lots of pew pew)
14:30 Loosing the Misfit to Kha’ak (and avenging it)
16:07 Going for resupplies and preparing for piracy
16:39 Ambushing the prey, a fat water freighter looking for a new owner
17:59 Starting the boarding operation
18:40 Realizing I need more support to deal with surprises
18:58 Stumbling over mentioned surprises, Kha’ak trying to crash the party
19:51 Sending more boarders as the first group fails
20:22 Finally going home with the price, a “slightly banged up” L water freighter

I’m wondering how to present ultra wide screenshots for a while now, because most people will not have an ultra wide display at hand or not run their browser in fullscreen on such a device. A scaled down version with retained ratio also just don’t really cut it:

Now what if we could wrap this in some sort of 360° image? This isn’t really 360°, of course but you get the idea. A quick search usually yields JS libs like Pannellum (https://pannellum.org/), which look great for this use-case as well and yes we could also solve this in CSS by using an animation and go for a little camera ride.

What if we could optionally also make use of a gyroscope though? You know, that sensor every mobile phone, tablet and VR device comes along with. So the user could device where to look just by moving the device around?

This was when I stumbled over A-Frame (https://aframe.io), which is basically a library for building 3D AR or VR experiences and while I may only scratching it’s surface with my quick tests here it does deliver exactly what I was looking for.

I built demos for various games today and I don’t know how long I’ll host the files here but they all follow the very same code pattern that I’ll add in the end:

https://beko.famkos.net/aframe-elite-dangerous.html

https://beko.famkos.net/aframe-fly-dangerous.html

https://beko.famkos.net/aframe-nms.html

https://beko.famkos.net/aframe-rebel-galaxy-outlaw.html

https://beko.famkos.net/aframe-spacebourne2.html

https://beko.famkos.net/aframe-starcitizen.html

https://beko.famkos.net/aframe-x4-foundations.html

Please be aware that I’m loading a ~5mb blob of JS code directly from A-Frame in the demos so don’t check them out if that is a problem for you. The image asset adds another whopping MB so please be patient. The best experience is on a mobile phone where you should be able to look around by moving the phone left and right. It works on a desktop browser too where the mouse can be used to look around.

Here is a code snippet that shows hows it’s done:

<!DOCTYPE html>
<html>
<head>
  <script src="https://aframe.io/releases/1.4.1/aframe.min.js"></script>
</head>
<body>
  <a-scene loading-screen="dotsColor: #ff6a00; backgroundColor: black">
    <a-assets>
      <img id="sky" src="./wp-content/uploads/2023/03/elite_dangerous_odyssey_for_my_valentine.jpg">
    </a-assets>
    <a-entity id="rig" position="-8 0 0" rotation="0 90 0">
      <a-entity id="camera" camera="fov:45; zoom: 1" far=90 look-controls></a-entity>
    </a-entity>
    <a-text color="#fff" value="Elite Dangerous ...on a canvas" width="3" position="-10.5 -0.5 1.5"
      rotation="0 135 9"></a-text>
    <a-curvedimage src="#sky" height="20.0" radius="10" theta-length="180" rotation="0 180 0"
      scale="2.5 1 2.5"></a-curvedimage>
    <a-sky rotation="0 0 0" position="0 0 0" color="#000"></a-sky>
  </a-scene>
</body>
</html>

Feel free to copy this snippet and play around with it. Just keep in mind that you have to use _local_ assets too or they won’t show up. Make sure to read the documentation too and play with the built in inspector opened with the key combination ctrl + alt + i.

And yes I’ll happily take a CSS only variant too but I really doubt that’s possible without loosing features like gyroscope data usage.

I didn’t use my Steam Link for some time and was kinda surprised by the new UI in Big Picture Mode. And also very unhappy because it was a stutter feast with buffer artefacts all over the place. Once I could get a game running it was butter though so something was up with the streaming mode of the UI. I’ve no really an idea what’s going on there but this was always a problematic thing with my AMD GPU under Gnome using Wayland when it comes to streaming and remote play. I ticked off the basics and disabled the blocklist for unknown GPUs, made sure that AMD hardware acceleration was enabled for the host in the Big Picture setting and even tried to launch it with the old big picture mode but no dice:

steam pipewire -pipewire-dmabuf -oldbigpicture

After reading around a lot on the bugtracker at https://github.com/ValveSoftware I eventually learned that the hardware acceleration for remote play is usually done with VAAPI and that there is debug information in ~/.local/share/Steam/logs/streaming_log.txt and sure enough here it was:

ffmpeg verbose: libva: VA-API version 1.16.0
ffmpeg verbose: libva: User environment variable requested driver 'radeonsi'
ffmpeg verbose: libva: Trying to open /usr/lib/dri/radeonsi_drv_video.so
ffmpeg verbose: libva: Found init function __vaDriverInit_1_16
ffmpeg verbose: libva: va_openDriver() returns 0
ffmpeg verbose: Initialised VAAPI connection: version 1.16
ffmpeg verbose: VAAPI driver: Mesa Gallium driver 22.3.5 for AMD Radeon RX 6700 XT (navi22, LLVM 15.0.7, DRM 3.49, 6.1.11-200.fc37.x86_64).
ffmpeg verbose: Driver not found in known nonstandard list, using standard behaviour.
ffmpeg verbose: Input surface format is nv12.
ffmpeg verbose: Compatible profile VAProfileH264Main (6) is not supported by driver.
ffmpeg error: No usable encoding profile found.

So the profile was missing and a check with vainfo confirmed this:

vainfo --device /dev/dri/renderD128 --display drm
Trying display: drm
libva info: VA-API version 1.16.0
libva info: Trying to open /usr/lib64/dri/radeonsi_drv_video.so
libva info: Found init function __vaDriverInit_1_16
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.16 (libva 2.16.0)
vainfo: Driver version: Mesa Gallium driver 22.3.5 for AMD Radeon RX 6700 XT (navi22, LLVM 15.0.7, DRM 3.49, 6.1.11-200.fc37.x86_64)
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            :	VAEntrypointVLD
      VAProfileMPEG2Main              :	VAEntrypointVLD
      VAProfileJPEGBaseline           :	VAEntrypointVLD
      VAProfileVP9Profile0            :	VAEntrypointVLD
      VAProfileVP9Profile2            :	VAEntrypointVLD
      VAProfileAV1Profile0            :	VAEntrypointVLD
      VAProfileNone                   :	VAEntrypointVideoProc

This was the moment when my brain did pull off one of it’s tricks and remembered me about the story about Fedora _disabling_ hardware acceleration for H264 due to proprietary concerns some months ago and yes I did recently upgrade to Fedora 37 🤯

Thankfully the community stepped in already and fixed mesa drivers are only one dnf install away on rpmfusion, so there is no need to recompile this with h264 support (and some others) manually. There is a caveat though because the swap command would happily delete the needed 32bit versions for Steam and only install the 64bit version of the swapped package. Keeping this in mind the required commands are basically this (and if this breaks your system I do not want to hear about it – use your brain!):

dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
dnf update
dnf swap mesa-va-drivers mesa-va-drivers-freeworld
dnf install mesa-va-drivers-freeworld.i686

And sure enough vainfo now has a way more complete list – including the previous missing VAProfileH264Main profile:

libva info: VA-API version 1.16.0
libva info: Trying to open /usr/lib64/dri/radeonsi_drv_video.so
libva info: Found init function __vaDriverInit_1_16
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.16 (libva 2.16.0)
vainfo: Driver version: Mesa Gallium driver 22.3.5 for AMD Radeon RX 6700 XT (navi22, LLVM 15.0.7, DRM 3.49, 6.1.11-200.fc37.x86_64)
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            :	VAEntrypointVLD
      VAProfileMPEG2Main              :	VAEntrypointVLD
      VAProfileVC1Simple              :	VAEntrypointVLD
      VAProfileVC1Main                :	VAEntrypointVLD
      VAProfileVC1Advanced            :	VAEntrypointVLD
      VAProfileH264ConstrainedBaseline:	VAEntrypointVLD
      VAProfileH264ConstrainedBaseline:	VAEntrypointEncSlice
      VAProfileH264Main               :	VAEntrypointVLD
      VAProfileH264Main               :	VAEntrypointEncSlice
      VAProfileH264High               :	VAEntrypointVLD
      VAProfileH264High               :	VAEntrypointEncSlice
      VAProfileHEVCMain               :	VAEntrypointVLD
      VAProfileHEVCMain               :	VAEntrypointEncSlice
      VAProfileHEVCMain10             :	VAEntrypointVLD
      VAProfileHEVCMain10             :	VAEntrypointEncSlice
      VAProfileJPEGBaseline           :	VAEntrypointVLD
      VAProfileVP9Profile0            :	VAEntrypointVLD
      VAProfileVP9Profile2            :	VAEntrypointVLD
      VAProfileAV1Profile0            :	VAEntrypointVLD
      VAProfileNone                   :	VAEntrypointVideoProc

And sure enough the Steam Link started working again. Somewhat. Now I have issues that some games don’t get captured or loose focus eventually but that I’ll debug another day 😩

Video: Starting Steamworld Dig 2 and showing system overview

Linux Gaming in 2023 is easy. Remote Play… not so much.

Some time ago I needed a virtual machine and while I’m not entirely sure any more why that was I did seem to have an inspirational moment and made a template of this. Here is what the config for _may_ look like:

agent: 1
arch: aarch64
bios: ovmf
boot: cdn
bootdisk: scsi0
cores: 2
efidisk0: misfits-btrfs:501/vm-501-disk-0.raw,size=64M
ipconfig0: ip=192.168.2.251/32,gw=192.168.2.1
memory: 1024
name: arm-test2
nameserver: 192.168.2.1
net0: virtio=96:79:F4:02:A1:6B,bridge=vmbr2
numa: 0
ostype: l26
scsi0: misfits-btrfs:501/vm-501-disk-1.raw,size=8G
scsi1: local:iso/debian-10.6.0-arm64-netinst.iso,media=cdrom
scsi2: misfits-btrfs:501/vm-501-cloudinit.raw,media=cdrom,size=4M
scsihw: virtio-scsi-pci
serial0: socket
smbios1: uuid=63fe535c-1507-4528-8dee-2bd2d59b57f8
sockets: 2
vga: serial0

It makes sense to install the package cloud-init to some stuff can be set from outside of the machine.

…and yes, it’s just as slow as expected from an ARM 🤓

I’m also not entirely sure if this is really officially featured by Proxmox (just like btrfs 🤷) but the machine was doing it’s job without an issue for years and I did just replay the template on VE 7.4 so I guess it’s fine 🤷

This is a project I kept postponing for years but when I eventually got my hands on all the required parts I had no longer an excuse and eventually built the first. It’s a portable music player for children that does not require internet access. It features selections of pre-installed music or audio books via RFID cards, that may come in all shapes and may even be integrated in toys. There are also 3 to 5 playback controls in the form of huge arcade buttons. Ideal especially for our middle one, who has to endure stationary stay for most of the week in a hospital.

And while this box is still missing proper decorations and button decals it’s full functional and portable. Also hey, kids ain’t stupid – they find the proper button without decal too. Even the baby found out where to put the RFID cards for the music to change 😉

The leg work for this was done by @xfjx@chaos.social and the project is described in great detail at https://www.voss.earth/tonuino/ – I did however not order the offered PCB and just soldered everything to a generic maker board to keep the costs down. Just like the arcade buttons, that I had left over from another project, I also have a bunch of such boards. The speaker was salvaged from an old entertainment system that broke down long ago and the box… ah well I guess it speaks for itself. Can’t say I was happy with the drill but the box was just perfect for our purpose.

First we built a test setup after salvaging all the needed hardware. The Ardunio parts are off the shelf, nothing special here. I had to improvise a little on the wiring due to missing wires. I opted for the older branch that just needs Arduino Studio, to install the software itself. There is a more modern version using platformIO but something with that does not like my vscode and I never managed to successfully compile it.

I eventually got the idea how the RFID cards worked and could be trained to the system and also did some tests like it’s maximum power usage. It has a passive speaker and cranked up to max it would consume 0.09A max – and on regular volume it was sitting at comfortable ~0.06A. Which is pretty fine. This would run for days with a decent power bank that could be dropped right into the box later if no external PSU is used.

Next was preparing the box. Luckily I had just the right drill for the buttons but making the holes was a pain in the neck. This had to be done very slow because the hard plastic would easily rip and splinter. I opted for a very massive USB connector in the end because the microUSB one used first broke on the 3rd use already. That was probably a little bit too cheap. The replacement is way more sturdy, which is kinda what I want for the children anyway. Everything the box needs to operate, like an old phone charger, a very long USB cable, and the RFID cards do fit inside the box for transport.

So one of the questions left was what to put on it’s internal SD card. Some of their favourite music, of course. What else though? Easy. We have a public audio centre at https://www.ardaudiothek.de/ offering a lot of stories and podcasts even for children. Downloading them one by one manually was cumbersome though. Luckily @1337core@chaos.social was just releasing his first version of Audiothek Downloader at https://github.com/Leetcore/audiothek-downloader so I had more gigabytes than the SD card could manage in minutes. The only issue was that the SD card needs the audio files enumerated so I did some quick scripting to rename the downloaded files. I had also no use for the downloaded cover images. It’s not beautiful but it got the job done:

#!/bin/bash

folder=$1
oldpwd=`pwd`

if [[ -z $folder ]]; then
    echo "Missig paramater id"
    exit
fi

folder="output/${folder}"

if [[ ! -d ${folder} ]]; then
    echo "Missig folder ${folder}"
    exit
fi

cd $folder
shopt -s extglob
for filename in +([0-9])_*.*; do
    [ -e "${filename}" ] || continue
    oldfile=${filename}
    # remove including the first underscore to get the index
    index=${filename%%_*}
    index=${index##+(0)}

    # pad the number with zeros
    newfile=`printf %03d ${index}`
    # combine new index with old filename, remove up and including first underscore
    newfile=${newfile}_${filename#*_}
    if [[ ! -f ${newfile} ]]; then
        mv -v "${oldfile}" "${newfile}"   
    fi
done

declare -i n=1
declare -i i=1

for filename in *.mp3; do
    [ -e "$filename" ] || continue

    target_dir=`printf %02d ${i}`
    if [[ ! -d ${target_dir} ]]; then
        mkdir ${target_dir}
    fi
    
    target_file=`printf %03d ${n}`

    if [[ ! -f "${target_dir}/${target_file}" ]]; then
        mv -v "${filename}" "${target_dir}/${target_file}.mp3"
    fi
    n+=1

    if (( n > 255 )); then
        n=1
        i+=1 
    fi

done

cd $oldpwd
exit 0 

This goes into e.g. to-tonUINO.sh into the root folder of the Audiothek Downloader where it can be executed after downloading a category. Like this for example:

python3 audiothek.py --url 'https://www.ardaudiothek.de/sendung/big-baeaeaem-wissen-ohne-filter/96510766/'
./to-tonUINO.sh 96510766
Renamed '24_Warum_mobben_wir_andere.mp3' -> '024_Warum_mobben_wir_andere.mp3'
Renamed '25_Warum_bekommen_Mädchen_bessere_Noten.mp3' -> '025_Warum_bekommen_Mädchen_bessere_Noten.mp3'
Renamed '26_Wie_sieht_die_Schule_der_Zukunft_aus.mp3' -> '026_Wie_sieht_die_Schule_der_Zukunft_aus.mp3'
Renamed '024_Warum_mobben_wir_andere.mp3' -> '01/001.mp3'
Renamed '025_Warum_bekommen_Mädchen_bessere_Noten.mp3' -> '01/002.mp3'
Renamed '026_Wie_sieht_die_Schule_der_Zukunft_aus.mp3' -> '01/003.mp3'

The resulting folder|s can be renamed, depending on what is already on the SD card, and moved to the SD card. It also makes sense to set the RFID card to audiobook mode so the TonUINO saves the position for the listener and does not start at the beginning again.

Now it’s up to the children to do some decorations. Our oldest wants her version built into a box that looks like a book. Hope we can get that one done soon too.

I usually play on Linux PC. I switched to Proton because I was eager to see some upcoming changes, like support, on the public_beta branch. And while this works[1] I was once more flabbergasted how complicated it is to set my desired display resolution of 5760×1200. I’m using a multihead setup with several displays and as usual the game engine would not let me _simply_ set that. Even in windowed mode (I mean I get that this won’t work with fullscreen).

There are several ways to work around this, especially with Proton, but I was looking for the prefs file I know from Linux. I found it in the end in the file compatdata/1781750/pfx/user.reg (that’s like the Windows registry but as plain file read by Wine) where the values are stored as dword under [Software\\StarGoat\\FlyDangerous]. In hex.

"Screenmanager Resolution Height_h2627697771"=dword:000004b0
"Screenmanager Resolution Width_h182942802"=dword:00001680
"Screenmanager Resolution Use Native_h1405027254"=dword:00000000

So 0780 and 04b0 are in the end 5760 and 1200. And sure enough, on the next game start I get _my_ desired resolution:

Sadly when I change settings in the game this gets overwritten again – so keep a backup around and drop it in again. This may even be added to a script – let’s see how long until this gets on my nerves and I automate that.

For the interested: This is how the same thing looks on the native version in the file ~/.config/unity3d/StarGoat/FlyDangerous/prefs

<pref name="Screenmanager Resolution Height" type="int">1200</pref>
<pref name="Screenmanager Resolution Width" type="int">5760</pref>
<pref name="Screenmanager Resolution Use Native" type="int">0</pref>

Why games|engines in 2023 still seem to have ideas about screen layouts is frankly beyond me.

Update: really eases the pain here as well. See also https://SimPit.dev/games/fly-dangerous/ how to use that with Steam.

[1] Headtracker quick test recordings: https://www.youtube.com/watch?v=13L0GlQyf_Q / https://tube.tchncs.de/w/fTYSUc9fTBmnTLHp2fpW4n

Some weeks ago I started making a ship for based on NZ-43 (14C) and while I was happy with the basic result it helped me mostly to get an understanding how such ships were made.

I never cared much about ships before and had absolutely no idea about this topic at all. During my research to close that gap, which consisted mostly of reading into Flevobericht, 331 (ISBN 9036910862) and following the awesome actual model builds by @silverman834 at https://modelshipworld.com/topic/25300-a-small-cog-by-silverman834-scale-120-c-1410-finished/ did I decide to reapply the lessons learned and go for the famous so called “Bremen Cog” ship.

This is a very specific ship type that was widely used from the 12th century on for trade via the sea. It was between 15 to 25 meters long, had one square sail and was crewed by approximate 12 people that worked in shifts. Unlike other sailing ships it was very reliant on wind direction but it’s flat bottom permitted it to be beached without taking damage so it could be unloaded everywhere e.g. during low tide. The aftercastle on it’s stern deck makes for a very distinct impression and can be recognized from many period depictions of ships. Several full sized replica have been built to this date.

The “Bremen Cog” is the best preserved example of this ship type. It’s wreck from ~1380 was discovered in the Weser in 1962. It took almost 40 years until it could be presented to the public. It’s my understanding that the conservation techniques applied had to be developed first. It’s on display in the German Maritime Museum and the cog apparently played a huge role in the founding of the museum itself: https://www.dsm.museum/en/exhibition/exhibitions/bremen-cog

The museum is located in 27568 Bremerhaven / Germany (and closed during the wintertime). No idea when I’ll get the chance to visit this but the museum does also foster a YouTube channel and one of the most recent videos up on their channel is a drone flight around and through the Bremen Cog made by Dennis Vogt so make sure to check this out: https://www.youtube.com/watch?v=KjYigiyF014

So why did I take this effort on me to recreate this famous ship type once more in a game? Curiosity and hyper focus I guess. I can tell you it was cumbersome because the game does not support bend objects so everything is basically a block. It does also not feature tools for e.g. Bézier curves or something. I spent quite some hours trying to get the hull and proportions right and while the superstructures are kinda opinionated I’m really happy with the end result. I also saved a lot on the ropes and while I know in theory how this should work and look it’s just _too much work_ to get this right in the game. So I only went with the most important running ropes. I hope any navigators reading this can forgive me 😉

The final result of the Bremen Cog under sails

I also prepared a variant without a sail and maybe I’ll even create a version with a reefed sail and with another version of the bow someday. I don’t know yet for I feel very exhausted from this little side project for now.

The final result of the Bremen Cog without sails

It’s also very sparse on final details because I can imagine that the blueprints for this ship will see a lot of reuse on various servers of the game so it should be really easy to individualise each placement with different colours or textures or cargo.

Speaking of: The blueprints for Rising World (Unity) can be downloaded from here:

You’re free to share and adapt this work as indicated by the CC-BY-SA 4.0 license. Please do inform me if you make use of this simply because that would make me very happy. It’s not required though.

Working on a loosely based on NZ-43 (14C). It’s approximately 12m long 🙂

First time I’m trying my luck with a vessel and not a building. The curving is difficult to realise in tho.

It started life in the old Java version of the game because the new Unity version has no posters yet. I had to segment the plan of the cog (carved in a very bad resolution from a PDF) into several in-game posters that had to be aligned in-game again to get the proper measurements.

After that I moved the blueprint of the frame over to the new version and started putting planks on it. A cumbersome process during which I learned a lot. I’ll probably make another and more improved hull based on the gathered know how.

I also fell straight into another “not yet implemented” trap. RisingWorld has a flip command to mirror an object and I kinda assumed this would work with blueprints too. It does not. And I was really not looking forward to put plank on both sides of the frame.

Luckily most of the leg work to read the binary blueprints was done by @paulevs before who released https://github.com/paulevsGitch/BlueLib under the MIT license. It has been a while that I touched Java but I could come up with some code of my own that would flip the planks only (I used rounded cubes for the planks exclusively) making use of this lib and the very first try at it looked promising already.

Here is the source I came up with in case you wonder:

package blueprint.flip.maybe;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import paulevs.bluelib.blueprint.Blueprint;
import paulevs.bluelib.blueprint.BlueprintIO;
import paulevs.bluelib.blueprint.element.BlueprintElement;
import paulevs.bluelib.blueprint.element.BlueprintElementType;

public class App {
    public static BlueprintElement cloneBlueprintElement(BlueprintElement el) {
        BlueprintElement element = new BlueprintElement(el.type);
        element.setPosition(el.posX, el.posY, el.posZ);
        element.setSize(el.sizeX, el.sizeY, el.sizeZ);
        element.rgba = el.rgba;
        element.setRotation(el.rotX, el.rotY, el.rotZ, el.rotW);
        element.setSurfaceOffset(el.surfaceOffsetX, el.surfaceOffsetY, el.surfaceOffsetZ);
        element.texture = el.texture;
        return element;
    }

    public static Blueprint readBlueprint(String pathname) {
        File file = new File(pathname);
        Blueprint blueprint = null;
        try {
            blueprint = BlueprintIO.read(file);
        }
        catch (IOException exception) {
            exception.printStackTrace();
        }

        return blueprint;
    }

    public static void main(String[] args) {
        final Blueprint blueprint = App.readBlueprint("/path/to/Blueprint-flip-maybe/cog_base_split_1670726695.blueprint");
        System.out.println("Opened " + blueprint.name);
        System.out.println("Blueprint has " + blueprint.elements.size() + " elements");

        ArrayList<BlueprintElement> elements = new ArrayList<BlueprintElement>();

        blueprint.elements.forEach(element -> {
            if(element.type == BlueprintElementType.ROUNDED_BLOCK) {
                System.out.println("T: " + BlueprintElementType.getElementName(element.type));
                System.out.println("pX: " + element.posX + "pY: " + element.posY + "pZ: " + element.posZ + " rX: " + element.rotX + "rY: " + element.rotY + "rZ: " + element.rotZ);
                BlueprintElement el = App.cloneBlueprintElement(element);
                el.posX = el.posX * -1;
                el.rotY = el.rotY * -1;
                el.rotZ = el.rotZ * -1;
                System.out.println("pX: " + el.posX + "pY: " + el.posY + "pZ: " + el.posZ + " rX: " + el.rotX + "rY: " + el.rotY + "rZ: " + el.rotZ);
                elements.add(el);
            }
        });

        elements.forEach(element -> {
            blueprint.elements.add(element);
        });

        blueprint.name += "_flipped_X";

        File outputFile = new File("/path/to/Blueprint-flip-maybe/" + blueprint.name + ".blueprint");
        try {
            BlueprintIO.write(blueprint, outputFile);
        }
        catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

I’m kinda happy with the result. This Lib also allows me to change the texture of the elements so I don’t have to worry how the used texture during the construction may look in the end.

Now onwards to improve the curves. I really wish for a bend mode where the beginning would snap on to an existing object and the opposite plane could be moved around individually.

With (Unity) improving a lot lately we’re feature wise almost on par with the old Java version again. Due to my hobbies I’m playing on the server https://medievalrealms.co.uk/ where I usually construct buildings based on specific periods according to my understanding of timber-framed constructions. Which may not be the best to rely on but hey, it’s a game after all.

One of the features still missing is an ingame map. We do have the compass already though and with debug enabled we even get an exact position on the current map. And the new maps are huge! And since we’re building here in multiplayer it’s no wonder that this is a dire missed feature to get an idea where the others are and what they are building, because it’s not fun navigating with X,Y,Z alone to visit other players (and keep note of where the own spot is located).

So I was intrigued to see that the player @Bamse did what gamers tend to do when a feature is missing. They start some sort of helper app (or wiki or whatever). This resulted in a Cloud map project at https://qgiscloud.com/Bamse/MapMedievalRealms/ where players from the same server may add POIs and do the leg work of surveying the “new” world.

The only drawback (haha. sorry.) is: It’s a PITA to do the surveying because stopping every few meters to note down a bunch of coordinates takes hours! Someone had to do this though, because “my” isle – a piece of rock I randomly stumbled over after the latest server reset – was still missing! And while I clocked roughly ~700h on this game already I was not going to do that. I’m a programmer – which equals to lazy in my opinion. So I started scripting and after a few minutes came up with the following still crude solution:

echo "" > move.log
while true; do
	gnome-screenshot -w -f /tmp/snapshot.png && convert /tmp/snapshot.png -crop 165x30+905+975 /tmp/snapshot-cropped.tiff && tesseract /tmp/snapshot-cropped.tiff - -l eng --psm 13 quiet | awk 'match($0, /([[:digit:]]+[.][[:digit:]])+.([[:digit:]]+[.][[:digit:]]+).([[:digit:]]+[.][[:digit:]]+)/) { print substr($0, RSTART, RLENGTH)}' | awk '{ printf "%0.0f,%0.0f,%0.0f\n", $1, $2, $3}' >> move.log 
	sleep 2
done

This surely can be improved a lot but… minimum viable product. We’re still talking about a game. Here is what it does:

* Take a screenshot of the active window (Rising World while playing)

* Save it to /tmp (that’s in my RAM disk)

* Crop out the coordinates and convert it to tiff using `imagemagick`

* Run `tesseract` for OCR detection

* Pipe the result to awk and use a RegEx to identify three numbers

* Reformat the 3 numbers (remove the precision) and dump it in as csv-like log

* Sleep for 2 seconds and repeat until terminated

And in case you wonder why I used gnome-screenshot: I’m on and the usual suspects written for X do simply not work. I did recompile gnome-screenshots tho to disable the annoying flashing though so it’s silent now.

Why the awk program? Well, tesseract is good but the raw data looked something like this in the end and the RegEx cleans that up somewhat:

serene ep)
9295.2 95.4 2828.0 |
9295.2 95.4 2828.0 |
9296.4 95.4 2828.5 |
nn
9303.1 95.4 2838.5 |
9295.0 98.4 2857.65
9289.1 98.7 2868.1 (7
9296.5 96.7 2849.0 |»
9301.1 95.4 2835.5 |
9301.1 95.4 2835.5 |
nn

So I put this to a test and jogged around “my” isle and here are the results:

One(!) data point was misread during the ~15 minutes run. Not too shabby! That could easily be fixed manually and who knows… mebbe I’ll improve on the script to check for implausible spikes like that at some point.

I demoed the script to other players on the same server and some already started investigating into solutions to adapt this script to Windows. Just don’t ask me how to do that – I really wouldn’t know 😛

Updated 10th Dec 2022: A solution to do the same on Windows PC appeared on https://wiki.calarasi.net/en/public/medievalrealms/ocr-coordinates

Adulted much and did lots of mundane tasks in the house recently. Including some plumbing that was really overdue. Water starts to become my arch nemesis in our ageing building and leaks really do not improve over time.

On my list were 4 siphons, that needed replacement, a shower hose and a shower head. Some of this stuff was only held together by varnish and replacing all this was a mess.

Anyway, what I find really great is that some of the required parts could be obtained in environmental friendly packaging. Namely the shower head and three of the siphons. No further plastic was in the cartons. Really appreciate this.

Sadly that was not the case for the shower hose and the new kitchen armature. Especially the last came with formed foam. That could really do without too.

Oh yeah and remember the unexpected findings in the washing machine from https://beko.famkos.net/2022/06/21/6686269/ ? This time it was Siemens 0, Grass Trimmer 7 and I really wonder “will they ever learn?” This time the sieve was toast and needed replacement 😠