Friday Facts #392 - Parametrised blueprints

Posted by kovarex on 2024-01-05

Hello,
I'm going to cover a feature I only just finished.
I was thinking about this idea for years already.
I always thought the feature is too hardcore to be included, but I learned that it is usually a mistake to underestimate the players, so I gave it a go, and decided to share it right away.


Motivation

The most common motivational example is the train unloading station.
Typically, I have the whole setup in a blueprint: rails, train stop, filtered inserters to avoid contamination, etc.

This is nice, but whenever I build the blueprint I need to re-configure all the filtered inserters for the target item, and also change the name of the stop, and it is tedious.

The long monotonous process of setting up station after station.

There are 2 ways to solve it in 1.1:
  • Use circuit network, but it feels like an overkill (more on that later), and you also can't set the train stop name by circuit network at the moment.
  • Having one specific blueprint for each item, which sounds like a nightmare.


Parametrised blueprints

This naturally leads to the definition of what we want: We want to have a blueprint which doesn't have a specific item configuration, but rather is generic, and allows you to configure it differently each time you build it.

The question is, how to implement it without adding unnecessary GUI clutter in the way unless we care about this specific feature?

Reconfiguring existing blueprints

The first piece of the puzzle is a tool to reconfigure existing blueprints.

For simplicity, lets take this example of a constant combinator configured like this:

Constant combinator parametrisation

When we make a blueprint of it, we can now access the new main tool used for reconfiguration.

Blueprint parametrisation GUI

The first and most simple usage of this UI is to change all occurrences of some item or number in the blueprint to something else. If I want to change all the places where [X] signal is used in the blueprint to be [Y], I just change the value in the UI and confirm. The blueprint was just re-configured.
The same with changing all fives in a blueprint.

Practically every setting and number you can have in an entity can be reconfigured by this feature. Inserter filters, assembler recipes, circuit network settings, combinator configuration, logistic requests, inventory filters, even rich text icons.
The last one can be used to change the name of the train stop, as long as you make a rich text part of it.

This is already an improvement, as you can always re-configure the blueprint to a different item before building it, but it still isn't good enough.

Parameters

The first step was to define special IDs called parameters for items, recipes, fluids, and entities.

Parameters selection

These have no meaning outside of the parametrisation context, they are used just for the blueprint generic configuration. They are normally not selectable anywhere in the game outside the blueprint configuration menu, but for power users, there is an interface settings to make them actually available everywhere.

So, back to the original blueprint, we can reconfigure it like this:

Parametrised configuration

Here I specified all of the 3 IDs to be parameters, and the number 5 used in both of the items, to be parametrised as well. Filling up the name is not necessary, but it is useful for the user of the blueprint to know what is he asked for in the next step, when the blueprint is being built.

Whenever you try to build a blueprint configured this way, you get this small dialog, where you are asked to fill parameters for this specific instance of the blueprint:

Filling parameters empty

I care about details, so you can even see how the build preview changes as the parameters are being specified.

Alt icons update as parameters are chosen.

And once you press confirm, the blueprint is built with the desired configuration.

Setting up the stations is a breeze with the parameters

Dependant parameters

So this is already useful, but still not good enough. Why? Because sometimes parameters are expected to be related to each other, and forcing the user of the blueprint to always fill them up correctly is not good form.

What do I mean by the dependencies? Lets say, I have a blueprint to craft an item with 3 ingredients (parameters 1, 2, 3), and take the ingredients from the train network.
Naturally, I can make a big setup with 3 input stations each parametrised to be one of the inputs and row of assembling machines, parametrised to create the desired item (parameter 0).
But whenever I want to build this blueprint, I would have to remember and manually fill the 3 ingredients for the desired item, which would not only slow me down, but also open the possibility of a mistake.

This is why parameters can be configured to be an ingredient of another parameter automatically, instead of having to fill it in.

Dependent parameters

Parameter 1,2,3 are set to be ingredients of the parameter 0, so when this blueprint is being built, only the value of parameter 0 is asked for, and the remaining values are automatically filled out.

Dependent numbers

With number configuration, the way the dependency can be set is much more free, as math exists!
Lets look at this example:

Dependent numbers

We have a blueprint where 3 numbers are present, 100, 101 and 200. But for some reason, we only want the user to modify the value of 100, but the contraption just needs the second number to be 1 bigger, and the 3rd number to be double of the first.
This is why each parametrised number can be assigned a variable, and its value can be used in math formulas in all of the subsequent dependent numbers.

So in this case, if you fill (upon building the blueprint) the 100 to be 10 instead, it will automatically set the 101 to be 11 and the 200 to be 20.


Conclusion

Factorio has been compared to programming many times, and this is just another part of the analogy. Almost everything you can do with parametrised blueprints can be done through circuit network logic, so it looks almost redundant.

In programming, the parallel is the compile time function execution versus runtime function execution. Basically, if you know the result of the computation already while compiling the program, it would be a waste to calculate it every time the program is ran, you can just put the number directly into the program. Which is very similar to knowing, that this setup will always be filtered to take iron gear-wheels, so it feels little bit wasteful to make a circuit network logic around it, just to simplify the building process.

I would love to hear your feedback about this feature. Is it too much? Is it understandable? Can't you wait to use it? Let us know on the usual channels.