Skip to content

[EN] Phoenixvine's Multiblock Creator Script

Redeix edited this page Aug 2, 2025 · 4 revisions

Special thanks to Phoenixvine from PFT for sharing these scripts

Step 1)

Download these two files and place them in the same folder anywhere on your PC.

multi.bat multis.py

files

Step 2)

With your copy/paste gadget in copy mode, select your structure.

copy

Step 3)

Put your gadget into the template manager. You can put in a piece of paper and hit save to make sure its the right structure. Then hit copy to save the json to your clipboard.

manager

Step 4)

Run the .bat file, it should open the console and look like this:

run

Step 5)

Enter the json string that you copied from the template manager.

entered

Step 6)

Hit the enter key. It should run and output the new GTM structure format. You can now copy/paste and use it.

ran

.aisle("AAAAAAABAAABAAAAAAA", "AAAAAAABAAABAAAAAAA", "AAAAAAACCCCCAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAD")
.aisle("AAAAABAAAAAAABAAAAA", "AAAAABAAAAAAABAAAAA", "AAAACCAAAAAAACCAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("AAAAAAABAAABAAAAAAA", "AAAAAAACCCCCAAAAAAA", "AAACCAAAAAAAAACCAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("AAAAABAAAAAAABAAAAA", "AAAACCAAAAAAACCAAAA", "AACAAAAAAAAAAAAACAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("AAAAAAAACCCAAAAAAAA", "AAACCAAAAAAAAACCAAA", "ACCAAAAAAAAAAAAACCA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("ABABACCAAAAACCABABA", "ABACAAAAAAAAAAACABA", "ACAAAAAAAAAAAAAAACA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("AAAAACAAAAAAACAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("BABAAAAAAAAAAAAABAB", "BACAAAAAAAAAAAAACAB", "CAAAAAAAAAAAAAAAAAC", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("AAAACAAAEFGAAACAAAA", "AACAAAAABABAAAAACAA", "CAAAAAAABABAAAAAAAC", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAAHHHAAAAAAAA", "AAAAAAAAIIIAAAAAAAA", "AAAAAAAAIIIAAAAAAAA", "AAAAAAAAIIIAAAAAAAA")
.aisle("AAAACAAAEEJAAACAAAA", "AACAAAAAAEAAAAAACAA", "CAAAAAAAAEAAAAAAAAC", "AAAAAAAAAEAAAAAAAAA", "AAAAAAAAAEAAAAAAAAA", "AAAAAAAAAEAAAAAAAAA", "AAAAAAAAAEAAAAAAAAA", "AAAAAAAAAEAAAAAAAAA", "AAAAAAAAAEAAAAAAAAA", "AAAAAAAAAEAAAAAAAAA", "AAAAAAAAHEHAAAAAAAA", "AAAAAAAAIEIAAAAAAAA", "AAAAAAAAIKIAAAAAAAA", "AAAAAAAAIIIAAAAAAAA")
.aisle("AAAACAAAELLAAACAAAA", "AACAAAAABABAAAAACAA", "CAAAAAAABABAAAAAAAC", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAABABAAAAAAAA", "AAAAAAAAHHHAAAAAAAA", "AAAAAAAAIIIAAAAAAAA", "AAAAAAAAIIIAAAAAAAA", "AAAAAAAAIIIAAAAAAAA")
.aisle("BABAAAAAAAAAAAAABAB", "BACAAAAAAAAAAAAACAB", "CAAAAAAAAAAAAAAAAAC", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("AAAAACAAAAAAACAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("ABABACCAAAAACCABABA", "ABACAAAAAAAAAAACABA", "ACAAAAAAAAAAAAAAACA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("AAAAAAAACCCAAAAAAAA", "AAACCAAAAAAAAACCAAA", "ACCAAAAAAAAAAAAACCA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("AAAAABAAAAAAABAAAAA", "AAAACCAAAAAAACCAAAA", "AACAAAAAAAAAAAAACAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("AAAAAAABAABAAAAAAAA", "AAAAAAACCCCCAAAAAAA", "AAACCAAAAAAAAACCAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("AAAAABAAAAAAABAAAAA", "AAAAABAAAAAAABAAAAA", "AAAACCAAAAAAACCAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
.aisle("DAAAAAABAAABAAAAAAA", "AAAAAAABAAABAAAAAAA", "AAAAAAACCCCCAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAA")
   .where("A", Predicates.blocks("minecraft:air"))
   .where("B", Predicates.blocks("gtceu:stainless_steel_frame"))
   .where("C", Predicates.blocks("tfg:casings/machine_casing_red_solar_panel"))
   .where("D", Predicates.blocks("minecraft:oak_planks"))
   .where("E", Predicates.blocks("tfg:casings/machine_casing_iron_desh"))
   .where("F", Predicates.blocks("tfg:large_solar_panel"))
   .where("G", Predicates.blocks("gtceu:configurable_maintenance_hatch"))
   .where("H", Predicates.blocks("ad_astra:iron_plateblock"))
   .where("I", Predicates.blocks("gtceu:tempered_glass"))
   .where("J", Predicates.blocks("gtceu:ulv_energy_output_hatch"))
   .where("K", Predicates.blocks("gtceu:silver_block"))
   .where("L", Predicates.blocks("gtceu:ulv_input_bus"))

Step 7)

You will likely have to reformat the output a bit. Here is the example above cleaned up in Java form:

			.pattern(definition -> FactoryBlockPattern.start()
				.aisle("       B   B       ", "       B   B       ", "       CCCCC       ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("     B       B     ", "     B       B     ", "    CC       CC    ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("       B   B       ", "       CCCCC       ", "   CC         CC   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("     B       B     ", "    CC       CC    ", "  C             C  ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("        CCC        ", "   CC         CC   ", " CC             CC ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle(" B B CC     CC B B ", " B C           C B ", " C               C ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("     C       C     ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("B B               B", "B C             C B", "C                 C", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("    C   FFF   C B  ", "  C     B B     C  ", "C       B B       C", "        B B        ", "        B B        ", "        B B        ", "        B B        ", "        B B        ", "        B B        ", "        B B        ", "        EEE        ", "        GGG        ", "        GGG        ", "        GGG        ")
				.aisle("    C   HIF   C    ", "  C      I      C  ", "C        I        C", "         I         ", "         I         ", "         I         ", "         I         ", "         I         ", "         I         ", "         I         ", "        EIE        ", "        GIG        ", "        GKG        ", "        GGG        ")
				.aisle("    C   FFF   C    ", "  C     B B     C  ", "C       B B       C", "        B B        ", "        B B        ", "        B B        ", "        B B        ", "        B B        ", "        B B        ", "        B B        ", "        EEE        ", "        GGG        ", "        GGG        ", "        GGG        ")
				.aisle("B B             B B", "B C             C B", "C                 C", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("     C       C     ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle(" B B CC     CC B B ", " B C           C B ", " C               C ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("        CCC        ", "   CC         CC   ", " CC             CC ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("     B       B     ", "    CC       CC    ", "  C             C  ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("       B   B       ", "       CCCCC       ", "   CC         CC   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("     B       B     ", "     B       B     ", "    CC       CC    ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.aisle("       B   B       ", "       B   B       ", "       CCCCC       ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ", "                   ")
				.where("H", Predicates.controller(Predicates.blocks(definition.get())))
				.where("B", Predicates.frames(GTMaterials.StainlessSteel))
				.where("C", Predicates.blocks(ForgeRegistries.BLOCKS.getValue(TFGCore.id("casings/machine_casing_red_solar_panel"))))
				.where("E", Predicates.blocks(ForgeRegistries.BLOCKS.getValue(ResourceLocation.parse("ad_astra:iron_plateblock"))))
				.where("F", Predicates.blocks(ForgeRegistries.BLOCKS.getValue(TFGCore.id("casings/machine_casing_iron_desh")))
					.or(Predicates.abilities(PartAbility.IMPORT_ITEMS).setMaxGlobalLimited(2).setPreviewCount(1))
					.or(Predicates.abilities(PartAbility.MAINTENANCE).setExactLimit(1))
					.or(Predicates.abilities(PartAbility.IMPORT_FLUIDS).setMaxGlobalLimited(2).setPreviewCount(1))
					.or(Predicates.abilities(PartAbility.EXPORT_FLUIDS).setMaxGlobalLimited(2).setPreviewCount(1))
					.or(Predicates.abilities(PartAbility.PARALLEL_HATCH).setMaxGlobalLimited(1))
					.or(Predicates.abilities(PartAbility.OUTPUT_ENERGY).setExactLimit(1))
				)
				.where("G", Predicates.blocks(GTBlocks.CASING_TEMPERED_GLASS.get()))
				.where("I", Predicates.blocks(ForgeRegistries.BLOCKS.getValue(TFGCore.id("casings/machine_casing_iron_desh"))))
				.where("K", Predicates.blocks(ChemicalHelper.getBlock(TagPrefix.block, GTMaterials.Silver)))
				.where(" ", Predicates.any())
				.build()
			)

Optional

Currently the script accepts a json string inside the command line but that doesn't work if the json string is longer than the text limit. So I have a modified python script to read from a json file instead and output to a JS file.

Replace the code in 'multis.py' with this:

import re
import json


def transform_json(input_data):
    statePos_str = input_data.get("statePosArrayList", "")

    m_blocks = re.search(r"blockstatemap:\[(.*?)\](?:,|})", statePos_str)
    if not m_blocks:
        raise ValueError("Nie znaleziono blockstatemap w statePosArrayList.")
    blockstatemap_str = m_blocks.group(1)
    block_names = re.findall(r'Name:"(.*?)"', blockstatemap_str)

    # Wyciągamy startpos i endpos
    m_start = re.search(r"startpos:\{(.*?)\}", statePos_str)
    m_end = re.search(r"endpos:\{(.*?)\}", statePos_str)
    if not m_start or not m_end:
        raise ValueError("Nie znaleziono startpos lub endpos w statePosArrayList.")

    def parse_pos(pos_str):
        pos = {}
        for part in pos_str.split(","):
            key, value = part.split(":")
            pos[key.strip()] = int(value.strip())
        return pos

    startpos = parse_pos(m_start.group(1))
    endpos = parse_pos(m_end.group(1))

    x_dim = endpos["X"] - startpos["X"] + 1
    y_dim = endpos["Y"] - startpos["Y"] + 1
    z_dim = endpos["Z"] - startpos["Z"] + 1
    total_blocks = x_dim * y_dim * z_dim

    m_list = re.search(r"statelist:\[I;(.*?)\]", statePos_str)
    if not m_list:
        raise ValueError("Nie znaleziono statelist w statePosArrayList.")
    statelist_str = m_list.group(1)
    statelist_nums = [int(x) for x in statelist_str.split(",") if x.strip() != ""]
    if len(statelist_nums) != total_blocks:
        raise ValueError(
            "Liczba elementów w statelist nie zgadza się z wymiarami struktury."
        )

    block_to_letter = {"minecraft:air": " "}
    next_letter_ord = ord("A")

    def assign_letter(block_type):
        nonlocal next_letter_ord
        if block_type == "minecraft:air":
            return " "
        if block_type not in block_to_letter:
            block_to_letter[block_type] = chr(next_letter_ord)
            next_letter_ord += 1
        return block_to_letter[block_type]

    structure = []
    index = 0
    for _ in range(z_dim):
        layer = []
        for _ in range(y_dim):
            row = []
            for _ in range(x_dim):
                block_index = statelist_nums[index]
                index += 1
                block_type = block_names[block_index]
                letter = assign_letter(block_type)
                row.append(letter)
            layer.append(row)
        structure.append(layer)

    keys = {v: k for k, v in block_to_letter.items()}

    return {"structure": structure, "keys": keys}


def gen_output(data):
    output_lines = []

    for aisle in data["structure"]:
        rows_str = ["".join(row) for row in aisle]
        tmp = ", ".join(f'"{row}"' for row in rows_str)
        line = f".aisle({tmp})"
        output_lines.append(line)

    for key, block in data["keys"].items():
        output_lines.append(f'   .where("{key}", Predicates.blocks("{block}"))')

    return output_lines


def main():
    with open("input.json", "r", encoding="utf-8") as f:
        input_json = json.load(f)
    data = transform_json(input_json)
    lines = gen_output(data)

    with open("output.js", "w", encoding="utf-8") as out_file:
        out_file.write("\n".join(lines))


if __name__ == "__main__":
    main()

Now instead of asking for an input json string it will read a file in the folder called "input.json" which is where you will place your code. And write to a file inside the folder called "output.js". Also this will set air as " " instead of "A" for better readability.

Clone this wiki locally