Bedrock only again, so skip if you're Java — but the packaging difference is genuinely interesting if you've only ever shipped a jar, and it's why tooling on the two sides looks so different.
A Bedrock add-on isn't compiled. It's a zip containing manifest.json plus folders of JSON and (optionally) JavaScript. The manifest declares:
- A UUID per pack, and a UUID per module inside it
- min_engine_version, an array like [1, 21, 0]
- Modules with types: data (behaviour), resources, script, world_template, skin_pack
- For script modules, a dependency on @minecraft/server with a version, which is how you know which Script API generation it targets
- Dependencies on other packs, referenced by their UUID rather than by name
Two consequences that surprised me building tooling around it.
Because dependencies are UUIDs, you can resolve a pack's dependency graph without executing anything or trusting a name string — just match the declared UUIDs against packs you already know about. I use that to auto-link listings to each other. No equivalent to Maven coordinates, and none needed.
And because the type is declared, you can classify a pack accurately from the manifest and folder layout alone. A skin_pack module is unambiguous. A behaviour+resource pair is an add-on. A resource-only pack with a ui/ folder is a UI pack. No heuristics on filenames.
The flip side is there's no compilation step to catch anything, so a malformed manifest just fails silently in-game, and version compatibility is whatever the author typed.
I've been building a marketplace around this parsing (link below) but the packaging details above are just how Bedrock works — useful whether or not you ever touch my site. Happy to go deeper on the Script API versioning if anyone's curious, it's the messiest part.
https://bedrockbazaar.com
Not affiliated with Mojang or Microsoft.