MCME Wiki

This page says how to lay out a resource pack repository so that MCME's release pipeline can build it: which files go where, the rules each file must follow, which branches the pipeline builds, and how to see the result on your own computer before you release. It applies to new packs and to existing ones. What happens after you push is in The release pipeline.

Sodium pack or vanilla-only pack?

Decide this first. It sets the layout, the release script and the zip names.

Sodium pack Vanilla-only pack
Has 3D .obj models in assets/mcme/ Yes No
Release script releaseVanillaSodium.sh releaseGeneral.sh
Zips per release <Pack>-Sodium, -Vanilla, -Lite, each also as -Footprints <Pack>.zip and <Pack>-Footprints.zip
Conversion generateVanilla makes the Vanilla and Lite zips None: the repository is zipped as it is
Examples Human, Mordor, Paths of the Dead Dwarven, Rohan, Lothlorien

As soon as one blockstate or item points at an mcme: model with an .obj file, the pack must be a Sodium pack. A vanilla-only release zips those models unconverted. Only players with the Special Model Loader mod can render them, so everyone else sees missing-model blocks.

Layout of a Sodium pack

This is the layout of RP-Human, RP-Mordor and RP-PathOfTheDead on master.

RP-<Name>/
├── pack.mcmeta                 in every zip; see below
├── pack.png                    in every zip
├── license.txt                 in every zip
├── README.md                   in every zip
├── .gitignore                  never in a zip (nor is any name starting with a dot)
├── .github/workflows/check-shaders.yml   the shader check on GitHub
├── .mcme-shaders.json          which shader modules the pack turns on
├── .mcme-shaders.lock          written by the shader sync; commit it, don't edit it
├── assets/
│   ├── minecraft/
│   │   ├── blockstates/        which model each block state uses; may name mcme: models
│   │   ├── items/              item definitions; may name mcme: models
│   │   ├── models/             ordinary JSON models
│   │   ├── textures/
│   │   └── shaders/            the shader base (written by the sync) and your hooks
│   ├── sodium/shaders/         the shader base's Sodium copies (written by the sync)
│   └── mcme/
│       ├── models/block/       the 3D models: <name>.json + .obj + .mtl (+ .objmeta)
│       ├── textures/block/     the textures the .mtl files name
│       └── sml_load_scopes/    Special Model Loader's list of models (Sodium zip only)
├── mc26_3/                     the shaders as Minecraft 26.3 needs them (written by the sync)
├── vanilla/                    optional: files only the Vanilla and Lite zips get
└── 1_*/                        optional version overlays

The shader files, .mcme-shaders.lock and mc26_3/ are written by the shader sync, never by hand: see The shader base.

What ends up in which zip

In the repository Sodium zip Vanilla and Lite zips
pack.mcmeta, pack.png, license.txt, README.md Yes Yes. In pack.mcmeta, the word Sodium in the description becomes Vanilla.
Any other file at the top (changelog.txt, blockList.txt, …) Yes No
assets/ Yes, as it is Rebuilt: see below
vanilla/ No Merged in: see The vanilla folder
Top-level folders named 1_… Yes Yes, copied as they are
Overlay folders listed in pack.mcmeta, such as mc26_3/ Yes Yes, copied; the build then writes the newest shader base into mc26_3/
Any other top-level folder Yes No
Anything at the top whose name starts with a dot No No

How assets/ is rebuilt for the Vanilla and Lite zips:

How the conversion works has the full details.

pack.mcmeta

RP-Human's, as an example:

{
  "pack": {
    "pack_format": 88,
    "min_format": 88,
    "max_format": 97,
    "description": "MCME Human v4.1.5 for MC 26.3 (and 26.2)"
  },
  "sodium": {
    "ignored_shaders": ["fog.glsl", "terrain.fsh", "terrain.vsh"]
  },
  "overlays": {
    "entries": [
      { "min_format": 97, "max_format": 97, "directory": "mc26_3" }
    ]
  }
}

The 3D models in assets/mcme

Every 3D model is a set of files with the same name in assets/mcme/models/block/:

File Needed What it is
<name>.json Yes The model in Special Model Loader's format
<name>.obj Yes, or a shared …_parent.obj The geometry, in block units (0 to 1 is one block)
<name>.mtl Yes, unless the JSON names another one in mtl_override, or the .objmeta sets texture Names the texture in a map_Kd line
<name>.objmeta No Conversion settings: see How the conversion works

RP-Human's pine_leaves.json, shortened:

{
  "parent": "special-model-loader:builtin/obj",
  "model": "mcme:models/block/leaves_parent.obj",
  "mtl_override": "mcme:models/block/pine_leaves.mtl",
  "particle": "mcme:block/beech_leaves",
  "flip_v": true
}

The .mtl it names:

newmtl m_b2bff805-3e5a-c860-a1cb-7ffdc3695c42
map_Kd mcme:block/pine_leaves

Rules:

Blockstates and item definitions

They live in assets/minecraft/blockstates/ and assets/minecraft/items/, and point at 3D models with an mcme: identifier:

{
  "variants": {
    "": [
      { "model": "mcme:block/hornbeam_leaves" },
      { "model": "mcme:block/hornbeam_leaves_2" },
      { "model": "mcme:block/hornbeam_leaves_3" }
    ]
  }
}

The vanilla folder

vanilla/ is optional (RP-Human, RP-Mordor and RP-PathOfTheDead have none). It holds files only the Vanilla and Lite zips need, merged into the converted pack's assets/.

Without a vanilla/ folder the converter prints WARNING!!! Missing vanilla overrides folder. That is expected and harmless.

Layout of a vanilla-only pack

RP-<Name>/
├── pack.mcmeta
├── pack.png
├── license.txt
├── README.md
├── .gitignore
├── .mcme-shaders.json          if the pack uses the shader base, with what the sync writes
├── .mcme-shaders.lock
├── assets/
│   └── minecraft/
│       ├── blockstates/
│       ├── models/
│       ├── textures/
│       └── shaders/
└── mc26_3/

Branches

Branch Built by Released to
development Test releases on the RP server A test repository
master Production releases on the main servers The pack's own repository
Anything else Nothing Nothing

.gitignore

Keep it short. Nothing in a pack needs ignoring except editor and OS clutter:

# OS and editor files
.DS_Store
Thumbs.db
desktop.ini
.idea/
.vscode/
*.bak
*.tmp

Never ignore *.obj, and don't start from the stock Visual Studio or Python .gitignore. Those ignore *.obj, folders named obj/, build/ or release/, and *.meta and *.log files. An ignored .obj never reaches GitHub, so the server builds the pack without it. That happened to a test release in October 2026: its 3D blocks showed as missing models.

To check that a file is really committed, run git check-ignore -v <file>. It prints the rule that ignores the file, or nothing.

Don't commit OS clutter deeper in the tree either: only names that start with a dot at the top are kept out of the zips, so a committed assets/.DS_Store ships.

Try the conversion on your computer

The server runs the same converter, so a local run shows what a release will contain, with every warning, in a few minutes. You need Python 3.10 or newer and Git.

  1. Get the converter:

    git clone https://github.com/MCME/ResourcePackScripts.git
    cd ResourcePackScripts
    pip install -r requirements.txt
    
  2. Get Minecraft 26.2's resources. Start 26.2 once in the launcher, so the client jar is downloaded to versions/26.2/26.2.jar in your Minecraft folder (%APPDATA%\.minecraft on Windows). A .jar is a zip file: open it with any zip tool and extract its assets folder into a new folder, for example minecraft-26.2, next to ResourcePackScripts. Use 26.2, because the server does.

  3. Convert, from the ResourcePackScripts folder, with your pack checked out next to it:

    # Vanilla variant
    python generateVanilla/generateVanilla.py ../RP-Human ../out-vanilla ../minecraft-26.2 --objmc generateVanilla/objmc.py
    # Lite variant
    python generateVanilla/generateVanilla.py ../RP-Human ../out-lite ../minecraft-26.2 --objmc generateVanilla/objmc.py --limit 2
    
    • Always pass --objmc. Without it the converter looks for objmc.py in the folder you run it from.
    • Use a new, empty output folder every time. The converter adds to an existing folder but never deletes from it.
    • Read every WARNING, Error, Missing and Note: line. Not every message starts with WARNING. Troubleshooting says what each one means.
  4. Try it in game. Zip the contents of the output folder, so that pack.mcmeta is at the top of the zip, and put the zip in your resourcepacks folder.

Bring a new pack into the pipeline

  1. Create the repository under the MCME organisation as RP-<Name>, with master and development branches.

  2. Lay it out as a Sodium pack or a vanilla-only pack. For a Sodium pack, RP-Human's pack.mcmeta and license.txt are a good start. Don't copy RP-Human's .gitignore: use the short one above.

  3. Add the shader base: write a .mcme-shaders.json, run the sync and commit what it wrote. Copy ResourcePackScripts' ci/check-shaders.yml to .github/workflows/check-shaders.yml. See The shader base.

  4. Try the conversion locally and fix the warnings.

  5. Ask an operator to add the pack to the release automation, with:

    They need Example
    The pack's name in the pipeline: one word, letters only. Every zip is named after it, and staff type its first letters. Rivendell
    Sodium pack or vanilla-only Sodium
    The repository MCME/RP-Rivendell
    The test release repository A test repository, or MCME/RP-Rivendell itself
    The Minecraft versions it is for 26.2 and 26.3
    Where players should get it An RP region on the RP server, then the main servers

    Choose a name whose first letter isn't taken by another pack, and keep it short: every download URL (https://github.com/<owner>/<repo>/releases/download/<tag>/<zip>) must stay under 100 characters. The operators' side is in Resource pack server (operators only).

  6. Make the first test release on the RP server and check it in game (see The release pipeline).

Turn a vanilla-only pack into a Sodium pack

For a pack that so far is zipped as it is, and now gets .obj models.

  1. Commit the models properly. Remove *.obj and similar rules from .gitignore, then add every .obj, .mtl, .objmeta and model JSON under assets/mcme/models/block/, and the textures under assets/mcme/textures/.
  2. Bring the shader base in, if the pack doesn't have it yet: replace the pack's own text.vsh, fog.glsl and any objmc shaders by adding a .mcme-shaders.json and running the sync, with --force the first time. Commit what it wrote.
  3. Check pack.mcmeta. Optionally add Sodium to the description.
  4. List the models in assets/mcme/sml_load_scopes/, as RP-Human does.
  5. Try the conversion locally. Check that blocks only your pack has still appear in the Vanilla output. If one is missing, see Known limits.
  6. Ask an operator to switch the pack to releaseVanillaSodium.sh. Its zips get new names (<Pack>-Vanilla.zip instead of <Pack>.zip, and so on), and its server slots get the six-zip layout at the same time.
  7. Make a test release on the RP server and check it with a vanilla client, with the MCME modpack, and with /rp client lite.

Checklist before every release

Known limits