13. Recipe Modifiers [Advanced] - HellFirePvP/ModularMachinery GitHub Wiki

[Feature added in ModularMachinery version 1.9+]

As it stands now, a machine can only be built, have its recipes be done and that's it. However, one might want to open up possibilities for the user to "upgrade" the machine to provide more "Secondary output", more energy output, lower chance of consuming input, take less time to do a recipe, [and so on].

The core idea behind recipe modifiers is as follows: 'Instead of placing block "X" at position "x, y, z", you can instead place block "Y" there and gain to your recipes.'

In order for that to work as expected, be sure the blocks you want the user to place at a specific position are different from what the normal machine would require there. So if you allow "any stone variant" to be placed at position "1, 2, 1" BE SURE that the block you have to place at "1, 2, 1" to gain a specific modifier isn't any stone variant! Or in a more general sense: Be sure that the block you want the user to place in order to get a modifier isn't a subset of the block(s) normally placed on that position. The results if the user gets the modifier or not are not determined and can flip back and forth. This might lead to unstable system behavior and add overall load to the server.

With that in mind, let's have a look at how modifiers are specified and what they can do.

Modifiers have to be defined in the machine definition. So as an example going forward, the machine "alloy_furnace", that is shipped as a default/example machine together with ModularMachinery, is used.

{
    "registryname": "alloy_furnace",
    "localizedname": "Alloy Smelter",
    "modifiers": [
        {
            "elements": "modularmachinery:blockcasing@1",
            "x": 0,
            "y": 1,
            "z": 0
        }
    ],
    "parts": [
        {
            ...
        },
[...]
        {
            "x": 0,
            "y": 1,
            "z": 0,
            "elements": "modularmachinery:blockcasing@2"
        },
[...]

So, as seen there, one part of a 'modifier' is just as the default elements in the "parts" array, just a block-definition which describes an offset and the block that needs to be placed there in order to "match". This can either be just a string defining one Blockstate, an array of blockstates or a blockstate-variable. How those definitions are supposed to be written should be clear by now. If not, please lookup the wiki pages on basic machine definitions.

However, now the user has no way of knowing which block(s) need to be placed where in order to get a modifier. So, a 'description' needs to be added so the user can know where to replace what. The mod can't do this on its own as a auto-generated description might be too long or too complex to understand for the player.

    [...]
    "localizedname": "Alloy Smelter",
    "modifiers": [
        {
            "elements": "modularmachinery:blockcasing@1",
            "x": 0,
            "y": 1,
            "z": 0,
            "description": "Replace block above controller with machine vent!"
        }
    ],
    "parts": [

A description can be added as shown in the example above. This should make it clear to the user what he has to do. The mod displays the description text below a preview of which block is needed to be placed to fulfill the modifier's conditions so as a pack maker you don't need to specifically name that block again. Additionally, this description should also include a short line as to what the modifier actually does, so the user knows about its effects! New-Lines are supported with '\n'. (Image example).

The description tag is optional (version 1.9.6 and newer) and if none is supplied, the replacement will not be explained/shown in the preview gui.

Now with the "replacement" part in place, the actual modifier can be defined:

    [...]
    "localizedname": "Alloy Smelter",
    "modifiers": [
        {
            "elements": "modularmachinery:blockcasing@1",
            "x": 0,
            "y": 1,
            "z": 0,
            "description": "Replace block above controller with machine vent\nfor double item output!",
            "modifier": {
                "io": "output",
                "target": "item",
                "operation": 1,
                "multiplier": 2.0
            }
        }
    ],
    ...

That is done in the "modifier" tag. A modifier needs multiple things:

  • "io":

    Defines the I/O-type of the recipe-component it should target. Can be either "input" or "output" and thus will target components handling input or output.

  • "target":

    Defines the type of recipe-component it should target. This can be either "item", "energy", "fluid", "duration" (for recipe processing time) or (if you have mekanism installed and gas-components) "gas". Addons like "Modular Diversity" can add other 'targets' that might have different names, such as "mana" or whatever the addon provides.

  • "operation":

    Defines the type of operation that should be applied. Possible operations: 0 = Addition, 1 = Multiplication. All "addition" modifiers will get added up before being applied to the actual value; All "multiplication" modifiers will be multiplied with each other before being applied to the actual value.

  • "multiplier":

    Defines the actual value that will be added or multiplied to the recipe-component's number.

  • "affectChance": [Optional]

    This was not defined in the example above. Can be either "true" or "false". Defaults to "false" if not defined. Defines if the multiplier should be applied to the recipe-component's chance instead of the actual value. (So for example the multiplier 2 with operation "multiply" should be applied to an item output's chance instead of its actual itemstack-amount. So if an item that has stacksize 3 would be output'ted with a chance of 0.4 / 40%, instead of multiplying its stacksize with 2, the chance that it would be produced is multiplied with 2; So when the modifier is applied, the chance of producing the item with stacksize 3 is 0.8 / 80% instead of 0.4 / 40%)

EXAMPLES: That was a lot of information. Some things are easier to understand with examples, so here are a few "modifier" tags and explanations as to what they will do to recipes if the modifier-condition is fulfilled for the machine.

    "modifier": {
        "io": "output",
        "target": "item",
        "operation": 1,
        "multiplier": 2.0
    }

The amount of item outputs that are produced by this machine is multiplied with 2.

    "modifier": {
        "io": "input",
        "target": "item",
        "operation": 0,
        "multiplier": -0.2,
        "affectChance": true
    }

The chance that an item is consumed as input is added with -0.2; So the chance gets lowered by 0.2 / 20%.

    "modifier": {
        "io": "output",
        "target": "energy",
        "operation": 1,
        "multiplier": 1.5
    }

The amount of energy that is produced gets multiplied by 1.5; In other words: is increased by 50%.

    "modifier": {
        "io": "output",
        "target": "fluid",
        "operation": 0,
        "multiplier": 50
    }

Any fluid that this machine produces/outputs is increased by 50mb. (Addition with 50)

    "modifier": {
        "io": "input",
        "target": "item",
        "operation": 1,
        "multiplier": 0,
        "affectChance": true
    }

The chance that an item is consumed as input is multiplied by 0. In other words: No items are consumed as inputs for any recipe.