Some days ago I stumbled on this game called shapez.io and, to my surprise, the game was both open source and built using web technologies.
I played it for some time and started to wonder how one would mod the game. Unfortunately, the game wasn't exactly built with mod support in mind, so the only way to actually add something was to edit its source code.
The game is built on top of a custom engine that, if I understood correctly, was adapted from another game the developer had built previously. This engine is not fancy with a lot of cranks and bolts like Phaser, but it gets the job done for the game. (No need for features that you won't use, right?)
The code is well documented and has a nice architecture overall; the main coder, tobspr, has done a good job with it. The code uses entity-component-system (ECS) to structure its many parts: each Entity can have many Components, each related to a System.
A Component adds attributes (rotation, variant, strength) to an Entity, while a System adds the actual logic to it.
I believe that Unity also uses this architecture for its engine.
Anyway...
I wanted to keep my feet on the ground and start simple, so the first thing I thought to add were belts with different colors. As the game uses the base additive colors a lot, I thought those would be my best bet for new belt colors that would fit the game theme.
Although in the past I managed to create pixel art for a college game, I don't consider myself an artist, so I had to find an easy way to create the new belt sprites. Maybe open each file and paint those little arrows... That would have been a hell of a task; luckily, the developer actually used a node/canvas script to generate the belts.
I just had to add a few hex colors and a for, and the job was done.
The game uses a sprite sheet for its images and Texture Packer to create its sprite atlases. You have to pay to use it, so I had to figure out a free alternative.
I looked around on npm for something that would help. Spritesmith looked promising, but didn't seem to do the job. I tried Spritesheet.js and it almost did the job... ALMOST.
The code had two flaws: a deprecated node API call, and it didn't send the scale value to the atlas JSON.
No matter the scale I used, in the output JSON it was always "1", so I fixed the code directly in the node_modules folder and later created a fork of spritesheet.js (I will probably create a pull request with the fix).
I wrote some npm scripts to generate the atlases that were needed, and done!
The only thing to note is that Texture Packer has more features and produces better sprite sheets: the game with my sprite sheets has some flicker on the sprite borders, and at the moment I didn't want to spend time fixing it.
Looking around the code, each building was created with the possibility of having variants. A trash bin has the storage variant, a 2-part cutter has a 4-part cutter variant, and so on.
Knowing this, the simplest way to add my belts would be to add belt variants without messing with any other part of its logic. It is just a visual aid mod anyway.
I added the belt variants, but it was still crashing, telling me that the game didn't understand that building code.
There must be some kind of registry somewhere...
Some greps later, I found the code to register buildings, and the building ids are incremental hardcoded numbers, which in my opinion is bad. If there were some sort of mod loader that would call each mod to register its buildings and they had to hardcode building ids, things would go south REALLY fast. I believe Minecraft had the same sort of problem before Forge.
Belts registered!
The MOD was complete and it worked!
If you want to see the actual code and changes made I suggest you look at github.
I hope you enjoyed, keep learning!
marcel0ll