This page covers how to make a 3x3x3 multi-block machine with a specific pattern. However, the same pattern applies when making it smaller or bigger. You will only need to adapt the procedure to check the correct blocks. The procedure is pretty massive, but it isn't hard to understand. You repeat the same logic for every block. Once you've got the logic of checking coordinates, you'll be able to adapt this tutorial to the case of your mod.
The objective
Before starting, it will be easier to understand if you have a reference of what we will try to achieve.
As you can see with the image, this multi-block machine will use 5 different blocks on 3 different layers, bottom
(left structure), middle
(center) and top
(right structure). Diamond blocks are used to make the 4 pillars of the machine and cover the gold block on its bottom and its top. The gold block is what we can name the core
of our machine. Finally, each cardinal direction (north, south, east, west) of the gold block is a Netherite block, except for one block. This block is our special/custom block. The user can only interact with the structure using this block. The multi-block machine will work, no matter what is the cardinal direction of this block compared to the gold block. This pattern has been chosen as it will help you in the procedure to understand what we will be checking.
Finally, in this example, when we click on the gray block (called "InterfaceBlock" in this tutorial), a GUI with 9 input slots opens.
Making the multi-block machine
As we want to use our machine as a chest, we will need to make a GUI and bind it to our custom block.
The GUI
In this case, we need a simple GUI with 9 input slots. We will also need to select "GUI with slots" for the GUI type, so the player will have access to his inventory.
When it's done, you can save and close it.
The custom block
Don't forget to enable the block entity otherwise, our block will never be able to store items. You will also need to uncheck the "Open bound GUI on right-click" parameter as we want to make some checks before opening it.
Then, go to the trigger page and create a new procedure into the "On block right clicked" trigger.
Save the procedure and return it to your block to save it. After this, you can close your block as we won't need it again.
Note: Later in the tutorial, I will call this procedure our "main procedure" and this block will be referenced as our "Interface block".
Checking all blocks
To make our job easier we will make a single procedure checking all required blocks for the machine with the core as the origin position. Don't worry about the orientation, we will cover this later in the tutorial.
Variables
To be easier to change in the example workspace, I decided to use some blockstate
variables. Check the image below for their meanings. You can of course use the name you want for each variable.
Bottom and top
We will begin by checking blocks of the bottom and top layers.
It's a lot of blocks, so it can seem complex, but we are simply checking the 9 blocks of the top layer.
Then, duplicate this group of blocks and change every y + 1
to y - 1
. After, add a new AND block and combine both groups.
However, it's pretty big, so to save some performances, you should collapse blocks (right-click on a block and "Collapse blocks").
2 layers are now done! 1 layer is remaining only.
Middle layer
We will continue with the 4 corners of the middle layer. It's the same 4 first blocks used in the previous image, except you don't check for y +/- 1
as we are on the same layer as our core block (the origin position).
All blocks we have checked for the moment are all blocks that aren't impacted by the orientation. This means we can put both groups of blocks in another AND block.
Grap an if/do/else
statement block inside the "Flow management" category and put our last AND block as the condition. You should get something similar to this.
Remaining blocks
We now need to check the 4 blocks impacted by the orientation. Those blocks are the 3 Netherite blocks and Interface block.
Depending on the orientation of the structure, the Interface block won't always be at the same coordinates compared to the core block. This means we need 4 conditions following this template.
When it's done, take another if statement and put this group as the condition. Then, to say to our main procedure the inventory can be opened, we will use a logic NBT tag and set its value to true. As this NBT tag is a tag for our Interface block, we need to put the coordinates of the Interface block. Take a look at the following image.
We are now checking one orientation. We now need to check for the 3 remaining ones. Don't be afraid, it's very easy.
Start by adding 3 else if
parts to the if statement. Then, duplicate the first condition and move the interfaceBlock
variable getter to the next block. Then, place it in the if statement and duplicate the "Set NBT logic tag". Don't forget to change the coordinates!
In the end, you should get this.
You can now place this if statement as the action of our first one.
All layers are now properly checked!
Disable the GUI
Now, you'll ask me why I told you to use a if/do/else
statement. It's pretty simple. If a player makes the machine once and then destroys it, what will happen? The player will still be able to open the GUI.
For this step, duplicate the if statement used to set the NBT tag. However, you can remove all crossBlockMiddleLayer
blocks (Netherite blocks in our example) and only keep conditions checking for our Interface block only. We want to disable the inventory because the machine doesn't have the right blocks, so we don't need to do further checks. You should get something like this image.
Then, duplicate this if statement and place it in the else statement of the other if statement (the one we used to set the NBT tag to true). This way, if checks don't success, we don't allow the player to use the inventory.
You can now save it one last time and we are done with this big procedure!
The main procedure
We've made a big procedure, but we don't use it yet. Let's make the main procedure, but don't worry! This procedure is much smaller than the previous one.
Variable
You may have noticed it, but we never checked the core block yet. We implied it was the right one. As explained earlier, we've made another procedure to check the entire machine because this way, we can simply need to take one point and do all checks from this point. However, we now need to check for our core block. It means another blockstate
variable named core
. We set its value to the gold block as it's the core block of our machine.
Checking the direction
To remember you, this procedure is executed when we right-click on our Interface block, so the core block (so the machine too) can be at the north, the south, the east or the west of this block.
To fix this problem, we check every cardinal position and call our big procedure with the coordinates of our core block as we took this block as the origin position in the procedure.
Now, no matter the rotation of the machine, it will be usable! Isn't it nice and much easier to make than making 4 times our other procedure?
Opening the inventory
Our Interface block has now its new value for the NBT logic time we used. We can now open the block's inventory or not depending on the value of our canOpenInventory
NBT tag.
Save your procedure and you're done with your multi-block machine!
Testing
Even we have finished the machine, you still need to check if everything is working. So open the game, create a new world (or open an existing one) and play with your first multi-block machine!