Kartones Blog

Be the change you want to see in this world

Book Review: Boinas Verdes: De Commandos a Pyro Studios

Review

Boinas Verdes: De Commandos a Pyro Studios book cover

Title: Boinas Verdes: De Commandos a Pyro Studios: un turbulento viaje del estrellato al olvido

Author(s): Jaume Esteve

The late nineties were a golden era for videogames, with so many great titles coming out, and most of them being released on PC. The Spanish game development scene was a far cry from the 8-bits era, but there were a few good studios remaining, and new ones appeared, like Pyro Studios. Their first game, Commandos: Behind Enemy Lines would would become an international success, but also a national example of how Spain could also create triple-A titles. The saga would spawn a trilogy, plus a mission pack (of the first game) and a first-person shooter spin-off, and the studio would release a few other titles, before pivoting to only mobile games, and lastly disappearing in 2017.

This book narrates the story of all the Commandos series games, but also tells us about cancelled prototypes of other titles, and the last decade, when they slowly faded away into nothingness. A story full of insanely hard work, some good and some (many?) bad decisions, and many, many human problems that would impede the studio from flourishing, and instead sentenced it. A story of some well known characters in the Spanish game development scene, but also of other hard workers that helped building the titles and might not have had enough recognition until now.

It is hard for me to not be subjective evaluating Boinas Verdes, because of two reasons. On the one hand I played all the titles, although, as we'll read that was common, I was one of those people who finished the first game, but then only purchased but didn't really finished the following ones (although I might now, except the FPS). On the other hand, I've had the pleasure to meet and briefly chat with a few of the main characters (except in the case of Unai Landa, that we've met a few times) and I admire them (even if, in some cases, they are not perfect).

The title covers a breadth of topics, and I was happy to find some technical details explained here and there, although always in a simple language that anybody can understand without technical knowledge. And how could a discussion about Pyro not mention Cops, a doomed title that could have been amazing (at least technically) but never materialized after 3 iterations and a lot of money invested? If anything, reading this book felt short, but around 250 pages it is quite packed, including some great illustrations and sketches of scenery and characters.

In summary, a great tribute to a great saga.


Ubuntu /bin and /sbin symlink to /usr/bin

Today I wanted to write about a quick Linux and Docker/containers tip. I might write more of these, as I have gathered a non-trivial amount of Linux and Ubuntu tips, tweaks and miscellaneous things (plus some related adventures at work) that might be worth sharing.

Since Ubuntu 20.04 (and earlier at Debian), /bin and /sbin are symlinks to /usr/bin. While this sounds nice and simple, it is good to be aware of this change when migrating containers from Ubuntu bionic to focal, because, if they copied any binary or script to /bin, now they will error.

The error if attempting to move stuff to /bin, while hinting the issue, is not 100% clear. It'll be something along the lines of:

ERROR: cannot copy to non-directory: /var/lib/docker/overlay2/<a-big-hash>/merge/bin

If you inspect the contents of the layer, or just do a quick test like RUN ls -al /bin before moving your script(s), you will notice the presence of the symlink instead of either nothing or a folder.

The solution is simple, just move the scripts to /usr/bin instead. And for clarity, change your script invocations to also run /usr/bin/<script-name>.sh and the like. Although /bin/<script-name>.sh will still work, it might not be clear why there are multiple, different paths.


Python Hashbang/Shebang

Until recently, I barely knew about Hashbangs or Shebangs other than, when building a shell script, you have to put #!/bin/bash at the first line of the file.

What I wasn't aware is that you can create scripts out of many file types, because the hashbang is a declaration of which interpreter to use when running the script... which means that you can run things like Python files as scripts.

Python works as a really good cross-platform language because the os and sys libraries allow to build platform-independent code (e.g. via path.join). But there is a small catch that you need to be aware of when marking a file as a script.

In general, you should strive for always pointing to python3:

#!/usr/bin/env python3

But if you still need to use python 2 (remember it reached end of life January 2020!) you should instead use python2:

#!/usr/bin/env python2

And, if you really need compatibility with both versions of python, the only solution is to use the generic python, because you can't specify both previous ones:

#!/usr/bin/env python

But here is the trick: Depending on the operating system, and especially on the more recent versions of Ubuntu, MacOS and the like, both the installed python version and/or any downloaded one might only be installed as python3. There is no guarantee that there will exist a symlink to the generic python (and can be dangerous to manually setup one).

How to solve supporting both versions then? Well, after reading the PEP-394, they advise to only use python if you plan to run the python script inside a virtual environment (venv or virtualenv).

So there you have it, a two-step approach to support both versions at once:

a) Always run the script inside a virtualenv (easy if you use Docker nowadays)

b) Define the shebang as

#!/usr/bin/env python


Web Speech API

I recently learned that there's a pretty decent Web Speech API, and I have the perfect (although outdated) pet project for it, my choose your adventure system: Lots of text that, with minimal cleaning, make for a nice reading.

There is a very practical online demo that will also give you a feeling of how good or bad the speech synthesizer will sound. And trust me, you should test it, as at least under Ubuntu Linux, Firefox sounds quite terrible, meanwhile Chrome is decent enough that I decided to target that browser for speech.

Most of the API consists on two objects, a single SpeechSynthesis instance to handle the main configuration, and then one SpeechSynthesisUtterance instance per sentence you wish to get read by the API.

I won't enter in the details of how to use it, because I merely followed the nice explanations and checked the source code of the demo (which are concise and good), but I will warn about one issue that I'm having with Chrome: If the sentence is too long, it gets cut, and the API seems to hang, not playing any further sound until closing and re-opening again the browser application!

In order to workaround the length limitation, I am applying the following simple split:

fullText.split(/[.,\:;!\?]| - /).forEach((textFragment) => {
    const text = textFragment.trim();
    if (text.length > 0) {
      const utterance = new SpeechSynthesisUtterance(text);
      utterance.voice = desiredVoice;
      utterance.pitch = pitchValue;
      utterance.rate = rateValue;
      synth.speak(utterance);
    }
  });

You can perfectly enqueue any number of "sentences" (utterances), just make sure that each is not too big.

I might improve the logic a bit in the future, mostly if I still find too big sentences I will try to discern the aprox. max length and split to the previous full word. Also note that when reading numbers (e.g. 5.6) it will split them. But overall, it is a nice first step, and really simple to use.


The Planet Crafter savegame editing

Note: This post refers to version 0.4 of the game.

I sometimes purchase early access videogames (not yet finished and sometimes even in alpha state) to support game developers. I don't do it often, though, because being an early adopter usually means coping with a lot of bugs and sometimes having to reset your game progress.

I am enjoying the slow, calm, and non-violent pace of The Planet Crafter, but with a recent update I faced a hard choice: start a new game to experience the new content, or keep with the old game and focus on finishing all the things I can... still eventually having to begin anew.

I decided to do something in the middle: Create a new savegame, but see how to alter the file and "cheat" by transferring as much as possible.

First of all, make a backup of the Survival-X.json file located at C:\Users\<your-username>\AppData\LocalLow\MijuGames\Planet Crafter folder (or a different drive if not installed in C:).

If you open that file, you will notice that is some kind of ndjson file, but using \n@\n as the line separator.

Useful tweaks

Terraform levels

You can recover your old terraforming levels by editing the first group in the file:

{"unitOxygenLevel":156052032.0,"unitHeatLevel":52146160.0,"unitPressureLevel":7044543.5,"unitBiomassLevel":5064053.0}

Unlocked things

Another of the first blocks contains a property called "unlockedGroups", if you also set that to your old values, when you reach the corresponding terraforming levels you will have again the extra unlocks (I think they are blueprint-based). Combined with the previous tweak it's a nice progress recovery. I for example had the following value:

"unlockedGroups":"MultiToolMineSpeed1,BootsSpeed1,HudCompass,MultiToolMineSpeed2,BootsSpeed2,podAngle,MultiToolMineSpeed3,RecyclingMachine,InsideLamp1,ScreenMap1,RocketMap1,Destructor1,Jetpack2,RocketMap2,MultiToolMineSpeed4,BootsSpeed3,DisplayCase,Pod4x,Jetpack3,MultiToolLight2,RocketMap3,RocketInformations1"

How items and inventory work

For context, this is how an item description line looks like:

{"id":204986269,"gId":"Backpack5","liId":0,"liGrps":"","pos":"0,0,0","rot":"0,0,0,0","wear":0,"pnls":"","color":"","text":"","grwth":0}|

And this is how a group looks:

{"id":1,"woIds":"209872472,202646469,202558410,202173013,204755405,202003892,204986269,206167325,202455419,203517384,205709091","size":12}|

From my research on the files, the basic rules are:

  • Biomes have their items inside, but until you pick, harvest, or deconstruct them, they "don't exist" as individual items in the save file
  • An item seems to be either placed in the world (when it has a non-zero "pos" attribute value), or inside a container ("liId" property is non-zero)
  • A container can be a storage item, your inventory, the items you're wearing
  • All normal items, including storage items, have an entry as an item
  • Storage items also have an entry as an item
  • Item ids seem to be unique, but I haven't tried crafting new ones or reusing the same id
  • A group represents a container item or a special container (equipment in use and inventory)
  • A group has an id attribute, which contained items will have set as their liId attribute
  • A group contains a woIds attribute that contains a comma-separated list of item ids
  • Inventory is a special group with "id":1
  • Equipment in use is a special group with "id":2
  • All items and groups except the last one have at the end of the line a | character

I played safe and didn't altered group "size" attribute, and just in case didn't messed with the equipment in use group. Instead I placed the desired items in the inventory, booted the game and equipped them in-game.

As I haven't added new items, what I do when I want to convert an item into another is to go pick some generic materials, save and exit, and edit, replacing them by my desired item. This in practice is just changing the "gId" attribute of the item.

This is a partial list of item gIds. (there's a bigger list at NexusMods) Note that they seem to be case sensitive, and sometimes contain typos or have case inconsistencies 😅:

  • Alloy
  • Aluminium
  • astrofood
  • Backpack1
  • Backpack2
  • Backpack3
  • Backpack4
  • Backpack5
  • Bacteria1
  • Bioplastic1
  • Cobalt
  • EquipmentIncrease1
  • EquipmentIncrease2
  • FabricBlue
  • Fertilizer1
  • Fertilizer2
  • FusionEnergyCell
  • HudCompass
  • ice
  • Iridium
  • Iron
  • Jetpack1
  • Jetpack2
  • Jetpack3
  • Magnesium
  • Mutagen1
  • MultiBuild
  • MultiDeconstruct
  • MultiToolLight
  • MultiToolLight2
  • MultiToolMineSpeed1
  • MultiToolMineSpeed2
  • MultiToolMineSpeed3
  • MultiToolMineSpeed4
  • Osmium
  • OxygenCapsule1
  • OxygenTank1
  • OxygenTank2
  • OxygenTank3
  • OxygenTank4
  • PulsarShard
  • PulsarQuartz
  • RedPowder1
  • Rod-alloy
  • Rod-iridium
  • Rod-uranium
  • Seed0
  • Seed1
  • Seed2
  • Seed3
  • Seed4
  • Seed5
  • Seed6
  • SeedGold
  • Silicon
  • Sulfur
  • Titanium
  • TreeRoot
  • Tree0Seed
  • Tree1Seed
  • Tree2Seed
  • Tree3Seed
  • Tree4Seed
  • Tree5Seed
  • Tree6Seed
  • Tree7Seed
  • Tree8Seed
  • Uranim
  • Vegetable0Seed
  • Vegetable1Seed
  • Vegetable2Seed
  • Vegetable3Seed
  • WaterBottle1
  • Zeolite

Summary

Being able to recover the old terraforming parameters and unlocks, your old equipment, and optionally altering items to ease things like having your nuclear power plants and labs again, makes it kind of similar to a "new game+" mode: You maintain your progress for all practical purposes, but you will still need to rebuild your base, and gather and grow plants and flora again.

Lately I'm having fun tweaking and modifying games when either I get a bit tired of them, I finish them but want to keep playing, or simply when faced with issues like progress resets, so expect similar posts on the topic in the near future.


Previous entries