minecraft-datapack-language


Nameminecraft-datapack-language JSON
Version 15.4.23 PyPI version JSON
download
home_pageNone
SummaryCompile JavaScript-style MDL language or Python API into a Minecraft datapack (1.21+ ready). Features variables, control flow, error handling, and VS Code extension.
upload_time2025-09-02 04:47:52
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseNone
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # <img src="https://github.com/aaron777collins/MinecraftDatapackLanguage/raw/main/icons/icon-128.png" width="32" height="32" alt="MDL Icon"> Minecraft Datapack Language (MDL)

A **modern JavaScript-style compiler** that lets you write Minecraft datapacks with **real control structures, variables, and expressions** that actually work.

๐Ÿ“– **[View Full Documentation](https://www.mcmdl.com/)** - Complete guides, examples, and API reference  
๐Ÿ“ฆ **[View on PyPI](https://pypi.org/project/minecraft-datapack-language/)** - Download and install from PyPI  
๐Ÿ”ง **[VS Code Extension](https://marketplace.visualstudio.com/items?itemName=mdl.minecraft-datapack-language)** - Syntax highlighting, IntelliSense, and snippets

![CI](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/CI/badge.svg)
![Test Examples](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/Test%20Examples/badge.svg)
![Documentation](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/Build%20and%20Deploy%20Documentation/badge.svg)
![PyPI](https://img.shields.io/pypi/v/minecraft-datapack-language?style=flat-square)
![Release](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/Release/badge.svg)

## ๐ŸŽฏ **MODERN** JavaScript-Style MDL Language

**MDL uses a modern JavaScript-style language format** with **real control structures, variables, and expressions**:

### โœจ **MODERN** Features
- **๐ŸŽฏ JavaScript-style syntax** with curly braces `{}` and semicolons `;`
- **๐Ÿ“ Modern comments** using `//` and `/* */`
- **๐Ÿ”ข Number variables** with `var num` type (stored in scoreboards)
- **๐Ÿ”„ Full control structures** including `if/else if/else`, `while` loops with method selection
- **๐Ÿ’ฒ Variable substitution** with `$variable$` syntax
- **๐Ÿงฎ Expressions** with arithmetic operations (`+`, `-`, `*`, `/`)
- **๐Ÿ“ฆ Namespace system** for modular code organization
- **๐ŸŽจ VS Code extension** with full IntelliSense and snippets
- **๐Ÿงช Comprehensive testing** with E2E validation
- **๐Ÿ“š Extensive documentation** with examples for every feature

### ๐Ÿ—๏ธ Core Features
- โœ… **Modern pack format 82** by default for latest Minecraft features
- โœ… **JavaScript-style syntax** with curly braces and semicolons
- โœ… **Real control structures** - `if/else if/else`, `while` loops with recursion/schedule methods
- โœ… **Number variables** stored in scoreboards with `$variable$` substitution
- โœ… **Expressions** with arithmetic operations and variable substitution
- โœ… **Multi-file projects** with automatic merging and dependency resolution
- โœ… **Variable optimization** - automatic load function generation for initialization
- โœ… **Selector optimization** - proper `@a` usage for system commands
- โœ… **Easy hooks** into `minecraft:tick` and `minecraft:load` via function tags
- โœ… **Tag support** for `function`, `item`, `block`, `entity_type`, `fluid`, and `game_event`

> **Note**: Version 12.0+ uses **pack_format 82** by default for the modern JavaScript-style syntax.

---

## ๐Ÿš€ Install

### Option A โ€” from PyPI (recommended for users)
Global, isolated CLI via **pipx**:
```bash
python3 -m pip install --user pipx
python3 -m pipx ensurepath    # reopen terminal
pipx install minecraft-datapack-language

mdl --help
```

Virtualenv (if you prefer):
```bash
python3 -m venv .venv
source .venv/bin/activate      # Windows: .\.venv\Scripts\Activate.ps1
pip install minecraft-datapack-language
```

### Option B โ€” from source (for contributors)
```bash
# inside the repo
python -m pip install -e .
```

---

## ๐Ÿ”„ Update

- **pipx**: `pipx upgrade minecraft-datapack-language`  
- **pip (venv)**: `pip install -U minecraft-datapack-language`  
- Pin a version: `pipx install "minecraft-datapack-language==<version>"` (replace `<version>` with desired version)

---

## ๐Ÿ’ป CLI

### Modern JavaScript-style MDL (v15.0+)
```bash
# Build JavaScript-style MDL files
mdl build --mdl my_pack/mypack.mdl -o dist --wrapper mypack
mdl check my_pack/mypack.mdl

# Validate generated mcfunction files
mdl check my_pack/mypack.mdl

# Multi-file projects
mdl build --mdl my_pack/ -o dist      # Build entire directory
mdl build --mdl "file1.mdl file2.mdl" -o dist  # Build specific files

# Create new projects
mdl new my_awesome_pack
```

### ๐Ÿ› **Comprehensive Error Handling**

MDL provides detailed error reporting with exact locations and helpful suggestions:

```bash
# Check for errors with detailed output
mdl check my_pack.mdl --verbose
```

**Example Error Output:**
```
Error 1: MDLSyntaxError in test.mdl:15:8
Missing closing brace for if statement
Context:
  13:   if (score > 10) {
  14:     say "High score!"
  15:     score = 0
  16:   }

Suggestion: Add closing brace '}' after line 15

Error 2: MDLLexerError in test.mdl:22:12
Unterminated string literal
Context:
  20:   say "Hello world
  21:   score = 10
  22:   say "Goodbye

Suggestion: Add closing quote '"' at the end of line 20
```

**Error Features:**
- โœ… **Exact Location**: Line and column numbers for precise error location
- โœ… **Context Lines**: Shows surrounding code for better debugging
- โœ… **Helpful Suggestions**: Specific fix recommendations
- โœ… **Multiple Error Collection**: Reports all errors, not just the first
- โœ… **Error Types**: Syntax, Lexer, Parser, Validation, File, Build, and Configuration errors

### Comments in MDL
MDL supports modern JavaScript-style comments:
```javascript
// Single-line comments
/* Multi-line comments */

pack "My Pack" {
    function example() {
        // This comment will be properly converted to mcfunction
        say Hello World!;
    }
}
```

Generated mcfunction files will have proper `#` comments:
```mcfunction
# This is a generated comment
say Hello World!
```

### Build a whole folder of `.mdl` files
```bash
mdl build --mdl src/ -o dist
# Recursively parses src/**/*.mdl, merges into one pack (errors on duplicate functions).
# Only the first file should have a pack declaration - all others are modules.
```

### Build multiple specific `.mdl` files
```bash
mdl build --mdl "src/core.mdl src/features.mdl src/ui.mdl" -o dist
# Parses multiple specific files and merges them into one datapack.
# Only the first file should have a pack declaration - all others are modules.
```

### Validate a folder (JSON diagnostics)
```bash
mdl check --json src/
```

---

## ๐Ÿ“ Quick Start - **MODERN** MDL

Create your first modern MDL project:

```mdl
// modern_pack.mdl
pack "Modern Pack" description "A modern example" pack_format 82;

namespace "example";

// Number variables with expressions
var num counter = 0;
var num health = 20;
var num level = 1;
var num experience = 0;

function "init" {
    say Initializing...;
    counter = 0;
    health = 20;
    level = 1;
    experience = 0;
}

function "tick" {
    counter = counter + 1;
    
    // Full if/else if/else control structure
    if "$health$ < 10" {
        say Health is low!;
        health = health + 5;
        effect give @a minecraft:regeneration 10 1;
    } else if "$level$ > 5" {
        say High level player!;
        effect give @a minecraft:strength 10 1;
    } else {
        say Normal player;
        effect give @a minecraft:speed 10 0;
    }
    
    // Variable substitution in strings
    say Counter: $counter$;
    
    // While loop with method selection
    while "$counter$ < 10" {
        counter = $counter$ + 1;
        say Counter: $counter$;
    }
    
    // Expressions with arithmetic
    experience = $level$ * 100 + $counter$;
    say Experience: $experience$;
}

// Lifecycle hooks
on_load "example:init";
on_tick "example:tick";
```

Build and test:
```bash
mdl build --mdl modern_pack.mdl -o dist
# โ†’ dist/modern_pack/... and dist/modern_pack.zip
```

---

## ๐Ÿ“ Multi-file Support

MDL supports building datapacks from multiple `.mdl` files. This is useful for organizing large projects into logical modules.

### How it works
- **Directory scanning**: When you pass a directory to `--mdl`, MDL recursively finds all `.mdl` files
- **File merging**: Each file is parsed into a `Pack` object, then merged into a single datapack
- **Conflict resolution**: Duplicate function names within the same namespace will cause an error
- **Pack metadata**: Only the **first file** should have a pack declaration (name, description, format)
- **Module files**: Subsequent files should **not** have pack declarations - they are treated as modules
- **Single file compilation**: When compiling a single file, it **must** have a pack declaration

### Best practices
- **One pack declaration per project**: Only the **first file** should have a pack declaration
- **Module files**: All other files should **not** have pack declarations - they are treated as modules
- **Single file requirement**: When compiling a single file, it **must** have a pack declaration
- **Organize by namespace**: Consider splitting files by namespace or feature
- **Use descriptive filenames**: `core.mdl`, `combat.mdl`, `ui.mdl` etc.
- **Avoid conflicts**: Ensure function names are unique within each namespace

### Example project structure
```
my_datapack/
โ”œโ”€โ”€ core.mdl          # โœ… HAS pack declaration
โ”œโ”€โ”€ combat/
โ”‚   โ”œโ”€โ”€ weapons.mdl   # โŒ NO pack declaration (module)
โ”‚   โ””โ”€โ”€ armor.mdl     # โŒ NO pack declaration (module)
โ”œโ”€โ”€ ui/
โ”‚   โ””โ”€โ”€ hud.mdl       # โŒ NO pack declaration (module)
โ””โ”€โ”€ data/
    โ””โ”€โ”€ recipes.mdl   # โŒ NO pack declaration (module)
```

**Important**: Only `core.mdl` should have a `pack "Name"` declaration. All other files are modules that merge into the main pack.

### Usage Examples

**Build from directory:**
```bash
mdl build --mdl my_datapack/ -o dist
```

**Build from specific files:**
```bash
mdl build --mdl "core.mdl combat.mdl ui.mdl" -o dist
```

**Check entire project:**
```bash
mdl check my_datapack/
```

**Check with verbose output:**
```bash
mdl build --mdl my_datapack/ -o dist --verbose
```

### Complete Multi-File Example

Here's a complete example showing how to organize a datapack across multiple files:

**`core.mdl`** (main file with pack declaration):
```mdl
// core.mdl - Main pack and core systems
pack "Adventure Pack" description "Multi-file example datapack" pack_format 82;

namespace "core";

// Number variables with expressions
var num system_version = 1;
var num player_count = 0;
var num total_experience = 0;

function "init" {
    say [core:init] Initializing Adventure Pack...;
    tellraw @a {"text":"Adventure Pack loaded!","color":"green"};
    system_version = 1;
    player_count = 0;
    total_experience = 0;
}

function "tick" {
    say [core:tick] Core systems running...;
    execute as @a run particle minecraft:end_rod ~ ~ ~ 0.1 0.1 0.1 0.01 1;
    player_count = player_count + 1;
    
    // Control structure example
    if "$player_count$ > 10" {
        say Many players online!;
        effect give @a minecraft:glowing 5 0;
    }
}

// Hook into vanilla lifecycle
on_load "core:init";
on_tick "core:tick";
```

**`combat/weapons.mdl`** (combat module):
```mdl
// combat/weapons.mdl - Weapon-related functions
namespace "combat";

var num weapon_damage = 10;
var num critical_chance = 5;

function "weapon_effects" {
    say [combat:weapon_effects] Applying weapon effects...;
    execute as @a[nbt={SelectedItem:{id:'minecraft:diamond_sword'}}] run effect give @s minecraft:strength 1 0 true;
    weapon_damage = weapon_damage + 2;
    
    // Expression example
    critical_chance = $weapon_damage$ / 2;
}

function "update_combat" {
    function core:tick;
    function combat:weapon_effects;
}
```

**`combat/armor.mdl`** (armor module):
```mdl
// combat/armor.mdl - Armor-related functions
namespace "combat";

var num armor_bonus = 5;
var num defense_rating = 0;

function "armor_bonus" {
    say [combat:armor_bonus] Checking armor bonuses...;
    execute as @a[nbt={Inventory:[{Slot:103b,id:"minecraft:diamond_helmet"}]}] run effect give @s minecraft:resistance 1 0 true;
    armor_bonus = armor_bonus + 1;
    
    // Expression with multiple variables
    defense_rating = $armor_bonus$ * 2 + 10;
}

function "update_armor" {
    function combat:armor_bonus;
}
```

**`ui/hud.mdl`** (UI module):
```mdl
// ui/hud.mdl - User interface functions
namespace "ui";

var num hud_version = 1;
var num display_counter = 0;

function "show_hud" {
    say [ui:show_hud] Updating HUD...;
    title @a actionbar {"text":"Adventure Pack Active","color":"gold"};
    hud_version = hud_version + 1;
    
    // While loop example
    while "$display_counter$ < 5" {
        display_counter = $display_counter$ + 1;
        say HUD update: $display_counter$;
    }
}

function "update_ui" {
    function ui:show_hud;
    function combat:update_combat;
    function combat:update_armor;
}
```

**Project structure:**
```
adventure_pack/
โ”œโ”€โ”€ core.mdl              # โœ… HAS pack declaration
โ”œโ”€โ”€ combat/
โ”‚   โ”œโ”€โ”€ weapons.mdl       # โŒ NO pack declaration (module)
โ”‚   โ””โ”€โ”€ armor.mdl         # โŒ NO pack declaration (module)
โ””โ”€โ”€ ui/
    โ””โ”€โ”€ hud.mdl           # โŒ NO pack declaration (module)
```

**Build the project:**
```bash
mdl build --mdl adventure_pack/ -o dist --verbose
```

This will create a datapack with:
- **Core systems** (initialization and tick functions)
- **Combat features** (weapon and armor effects)
- **UI elements** (HUD display)
- **Cross-module calls** (UI calls combat functions)
- **Variable optimization** (automatic load function generation)

### CLI Options for Multi-file Builds

- `--mdl <path>`: Path to `.mdl` file, directory, or space-separated file list
- `--src <path>`: Alias for `--mdl` (same functionality)
- `-o, --out <dir>`: Output directory for the built datapack
- `--wrapper <name>`: Custom wrapper folder/zip name (default: first namespace or pack name slug)
- `--pack-format <N>`: Minecraft pack format (default: 82 for modern syntax)
- `-v, --verbose`: Show detailed processing information including file merging
- `--py-module <path>`: Alternative: build from Python module with `create_pack()` function

### Error Handling

- **Missing pack declaration**: Single files must have a pack declaration
- **Duplicate pack declarations**: Only the first file in a multi-file project should have a pack declaration
- **Function conflicts**: Duplicate function names within the same namespace will cause an error
- **Clear error messages**: Errors include file paths and line numbers for easy debugging

---

## ๐ŸŽฏ **Explicit Scope System**

MDL features a powerful **explicit scope system** that makes variable access clear and unambiguous. Each variable access must specify its scope, eliminating hidden state and making code more readable.

### **Variable Declaration Scopes**

```mdl
// Player-specific variable (defaults to @s in execution context)
var num playerScore = 0;

// Server-wide variable (stored on server armor stand)
var num globalCounter scope<global> = 0;

// Team-specific variable
var num teamScore scope<@a[team=red]> = 0;

// Custom entity variable
var num entityData scope<@e[type=armor_stand,tag=special,limit=1]> = 0;
```

### **Variable Access with Explicit Scopes**

```mdl
// Each variable access must specify the scope
playerScore<@s> = 42;                    // Player scope
globalCounter<global> = 100;             // Global scope
teamScore<@a[team=red]> = 5;            // Team scope
entityData<@e[type=armor_stand,tag=special,limit=1]> = 10; // Custom entity
```

### **Explicit Scopes in Conditions**

**NEW!** MDL now supports explicit scope selectors in if/while conditions, allowing you to override declared variable scopes:

```mdl
function "check_scores" {
    // Check current player's score
    if "$playerScore<@s>$ > 10" {
        say "Your score is high!";
    }
    
    // Check global counter
    if "$globalCounter<global>$ > 100" {
        say "Global milestone reached!";
    }
    
    // Check another player's score
    if "$playerScore<@p[name=Steve]>$ > 20" {
        say "Steve has a good score!";
    }
    
    // Check team score
    if "$teamScore<@a[team=red]>$ > 50" {
        say "Red team is winning!";
    }
    
    // Use explicit scopes in while loops too
    while "$globalCounter<global>$ < 10" {
        globalCounter<global> = globalCounter<global> + 1;
        say "Counter: $globalCounter$";
    }
}
```

**Benefits:**
- **Override declared scopes**: Use different scopes than what was declared
- **Check other entities**: Compare scores across different players/teams
- **Flexible conditions**: Mix and match scopes as needed
- **Clear intent**: Explicit scope makes code more readable and debuggable

### **Scope Mapping**

MDL maps scopes to Minecraft selectors:

| MDL Scope | Minecraft Selector | Description |
|-----------|-------------------|-------------|
| `scope<global>` | `@e[type=armor_stand,tag=mdl_server,limit=1]` | Server-wide storage |
| `scope<@s>` | `@s` | Current player |
| `scope<@a>` | `@a` | All players |
| `scope<@a[team=red]>` | `@a[team=red]` | Red team players |
| `scope<@e[type=armor_stand,tag=something,limit=1]>` | `@e[type=armor_stand,tag=something,limit=1]` | Custom entity |

---

## ๐ŸŽฏ **Advanced Multi-File Examples with Namespaces**

### **Modern Namespace System**

MDL's namespace system allows you to organize code across multiple files with proper separation:

**`game.mdl`** - Core Game Logic:
```mdl
pack "multi_game" "A multi-file game example" 82;

namespace "game";

var num player_score = 0;
var num game_timer = 0;
var num health = 20;

function "main" {
    // If-else if-else chain
    if "$health$ < 10" {
        say "Health is low: $health$";
        health = $health$ + 5;
    } else if "$health$ > 15" {
        say "Health is good: $health$";
    } else {
        say "Health is moderate: $health$";
    }
    
    // While loop with counter
    while "$game_timer$ < 5" {
        game_timer = $game_timer$ + 1;
        say "Game Timer: $game_timer$";
    }
}

function "score_update" {
    player_score = $player_score$ + 10;
    say "Score updated: $player_score$";
}

on_tick "game:main";
```

**`ui.mdl`** - User Interface:
```mdl
namespace "ui";

var num menu_state = 0;
var num selected_option = 1;

function "main" {
    // Show menu based on state
    if "$menu_state$ == 0" {
        say "=== Main Menu ===";
        say "1. Start Game";
        say "2. Options";
        say "3. Exit";
    }
    
    // Handle selection
    if "$selected_option$ == 1" {
        say "Starting game...";
    } else if "$selected_option$ == 2" {
        say "Opening options...";
    } else if "$selected_option$ == 3" {
        say "Exiting...";
    }
}

function "button_handler" {
    var num button_id = 0;
    
    if "$button_id$ == 1" {
        selected_option = 1;
        say "Option 1 selected";
    } else if "$button_id$ == 2" {
        selected_option = 2;
        say "Option 2 selected";
    }
}

on_load "ui:main";
```

**`combat.mdl`** - Combat System:
```mdl
namespace "combat";

var num enemy_count = 5;
var num damage = 0;

function "main" {
    var num total_damage = 0;
    total_damage = $damage$ * 2;
    
    if "$total_damage$ > 20" {
        say "Critical hit! Damage: $total_damage$";
    } else {
        say "Normal hit. Damage: $total_damage$";
    }
    
    // Variable substitution in tellraw
    tellraw @a [{"text":"Enemy Count: "},{"score":{"name":"@a","objective":"enemy_count"}}];
}

on_tick "combat:main";
```

### **Build and Generated Structure**

```bash
# Build all files together
mdl build --mdl . -o dist

# Or build specific files
mdl build --mdl "game.mdl ui.mdl combat.mdl" -o dist
```

**Generated Structure:**
```
dist/
โ”œโ”€โ”€ data/
โ”‚   โ”œโ”€โ”€ minecraft/tags/function/
โ”‚   โ”‚   โ”œโ”€โ”€ load.json    # Contains all load functions
โ”‚   โ”‚   โ””โ”€โ”€ tick.json    # Contains all tick functions
โ”‚   โ”œโ”€โ”€ game/            # game.mdl namespace
โ”‚   โ”‚   โ””โ”€โ”€ function/
โ”‚   โ”‚       โ”œโ”€โ”€ main.mcfunction
โ”‚   โ”‚       โ””โ”€โ”€ score_update.mcfunction
โ”‚   โ”œโ”€โ”€ ui/              # ui.mdl namespace
โ”‚   โ”‚   โ””โ”€โ”€ function/
โ”‚   โ”‚       โ”œโ”€โ”€ main.mcfunction
โ”‚   โ”‚       โ””โ”€โ”€ button_handler.mcfunction
โ”‚   โ””โ”€โ”€ combat/          # combat.mdl namespace
โ”‚       โ””โ”€โ”€ function/
โ”‚           โ””โ”€โ”€ main.mcfunction
โ””โ”€โ”€ pack.mcmeta
```

### **Key Benefits of Namespace System**

- โœ… **No function name conflicts** - Each namespace is completely separate
- โœ… **Modular development** - Work on different features in separate files
- โœ… **Automatic merging** - All variables and functions are combined intelligently
- โœ… **Proper initialization** - Variables are automatically set up in load functions
- โœ… **Clean organization** - Each module has its own directory structure
- โœ… **Easy maintenance** - Update individual modules without affecting others

### **Complete Example Project**

Check out the `examples/multi_file_example/` directory for a complete working example with:
- Multiple namespaces (`test`, `other`, `ui`)
- Various control structures and expressions
- Comprehensive documentation
- Ready-to-build files

---

## ๐Ÿ“ The **MODERN** `.mdl` Language

### Grammar you can rely on (based on the parser)
- **pack header** (required once):
  ```mdl
  pack "Name" [description "Desc"] [pack_format N];
  ```
- **namespace** (selects a namespace for following blocks):
  ```mdl
  namespace "example";
  ```
- **number variable declarations** (only `num` type supported):
  ```mdl
  var num counter = 0;
  var num health = 20;
  var num level = 1;
  ```
- **function** (curly braces + semicolons):
  ```mdl
  function "hello" {
      say hi;
      tellraw @a {"text":"ok","color":"green"};
  }
  ```
- **full conditional blocks** (if/else if/else statements):
  ```mdl
  function "conditional" {
      if "$health$ < 10" {
          say Health is low!;
          effect give @s minecraft:glowing 5 1;
      } else if "$level$ > 5" {
          say High level player!;
          effect give @s minecraft:speed 5 1;
      } else {
          say Normal player;
          effect give @s minecraft:jump_boost 5 0;
      }
  }
  ```
- **while loops** (repetitive execution with method selection):
  ```mdl
  function "countdown" {
      var num counter = 5;
      while "$counter$ > 0" {
          say Counter: $counter$;
          counter = counter - 1;
      }
      
      // Schedule method for performance
      counter = 10;
      while "$counter$ > 0" method="schedule" {
          say Schedule counter: $counter$;
          counter = $counter$ - 1;
      }
  }
  ```
- **expressions** (arithmetic operations):
  ```mdl
  function "expressions" {
      var num a = 10;
      var num b = 5;
      var num result = $a$ + $b$ * 2;
      say Result: $result$;
  }
  ```
- **function calls** (one function invoking another with fully qualified ID):
  ```mdl
  function "outer" {
      say I will call another function;
      function example:hello;
  }
  ```
- **hooks** (namespaced ids required):
  ```mdl
  on_load "example:hello";
  on_tick "example:hello";
  ```
- **tags** (supported registries: `function`, `item`, `block`, `entity_type`, `fluid`, `game_event`):
  ```mdl
  tag function "minecraft:tick" {
      add "example:hello";
  }
  ```
- **comments** start with `//` or `/* */`. Hashes inside **quoted strings** are preserved.
- **whitespace**: empty lines are ignored; **explicit block boundaries** using curly braces `{` and `}`; **statement termination** using semicolons `;`.

> Inside a function block, **every non-empty line** is emitted almost verbatim as a Minecraft command. Comments are stripped out and multi-line commands are automatically wrapped. See below for details.

### Comments

MDL supports modern JavaScript-style comments:

- **Full-line comments** (a line starting with `//`) are ignored by the parser.
- **Block comments** (`/* */`) are supported for multi-line comments.
- **Inline `#` characters** are preserved inside function bodies, so you can still use them the way `mcfunction` normally allows.

Example:

```mdl
// Comment Demo - Testing comments
pack "Comment Demo" description "Testing comments";

namespace "demo";

function "comments" {
    // This whole line is ignored by MDL
    say Hello; // This inline comment is preserved
    tellraw @a {"text":"World","color":"blue"}; // Inline too!
    
    /* This is a block comment
       that spans multiple lines
       and is ignored by the parser */
}
```

When compiled, the resulting function looks like:

```mcfunction
say Hello # This inline comment is preserved
tellraw @a {"text":"World","color":"blue"} # Inline too!
```

Notice how the full-line `//` and block comments never make it into the `.mcfunction`, but the inline ones do.

---

### **MODERN** Variables and Data Types

MDL supports **number variables** with **expressions and arithmetic operations**:

#### Number Variables (`num`)
```mdl
var num counter = 0;
var num health = 20;
var num experience = 100;

// Arithmetic operations
counter = counter + 1;
health = health - 5;
experience = experience * 2;

// Expressions with multiple variables
var num total = $health$ + $experience$;
var num average = $total$ / 2;

// Variable substitution in strings
say Health: $health$;
say Experience: $experience$;
say Total: $total$;
```

**Variable Substitution**: Use `$variable_name$` to read values from scoreboards in strings and conditions.

**Expressions**: Support for arithmetic operations (`+`, `-`, `*`, `/`) with proper order of operations.

### **MODERN** Control Flow

MDL supports full conditional blocks and loops for control flow.

#### Conditional Blocks

MDL supports complete if/else if/else statements for conditional execution:

```mdl
function "conditional_example" {
    var num player_level = 15;
    var num player_health = 8;
    var num player_experience = 1000;
    
    if "$player_level$ >= 10" {
        if "$player_health$ < 10" {
            say Advanced player with low health!;
            effect give @s minecraft:regeneration 10 1;
            player_health = $player_health$ + 10;
        } else {
            say Advanced player with good health;
            effect give @s minecraft:strength 10 1;
        }
    } else if "$player_level$ >= 5" {
        say Intermediate player;
        effect give @s minecraft:speed 10 0;
    } else {
        say Beginner player;
        effect give @s minecraft:jump_boost 10 0;
    }
    
    // Expression in condition
    if "$player_experience$ > $player_level$ * 100" {
        say High experience for level!;
    }
}
```

**Rules:**
- Conditions use `$variable$` syntax for variable substitution
- **Explicit block boundaries**: Conditional blocks use curly braces `{` and `}`
- **Statement termination**: All commands must end with semicolons `;`
- You can have multiple `else if` blocks
- The `else` block is optional
- Conditional blocks are compiled to separate functions and called with `execute` commands
- **Proper logic**: `else if` blocks only execute if previous conditions were false
- **Expressions in conditions**: Support for arithmetic operations in conditions

#### While Loops

MDL supports while loops with method selection for repetitive execution:

```mdl
function "while_example" {
    var num counter = 5;
    
    // Default recursion method (immediate execution)
    while "$counter$ > 0" {
        say "Counter: $counter$";
        counter = $counter$ - 1;
    }
    
    // Schedule method (spreads across ticks for performance)
    counter = 10;
    while "$counter$ > 0" method="schedule" {
        say "Schedule counter: $counter$";
        counter = $counter$ - 1;
    }
    
    // Expression in loop condition
    var num max_count = 5;
    counter = 0;
    while "$counter$ < $max_count$ * 2" {
        say "Expression counter: $counter$";
        counter = $counter$ + 1;
    }
}
```

**Rules:**
- Conditions use `$variable$` syntax for variable substitution
- **Explicit block boundaries**: While loops use curly braces `{` and `}`
- **Statement termination**: All commands must end with semicolons `;`
- While loops continue until the condition becomes false
- **Method Selection**: Choose `method="recursion"` (default) or `method="schedule"`
- **Recursion method**: Executes all iterations immediately (good for small loops)
- **Schedule method**: Spreads iterations across ticks (better for long loops, prevents lag)
- **Important**: Ensure your loop body modifies the condition to avoid infinite loops
- **Expressions in conditions**: Support for arithmetic operations in loop conditions

**Implementation**: While loops generate separate function files with proper recursive calls to continue execution until the condition becomes false.

---

### Multi-line Commands

Long JSON commands can be split across multiple lines with a trailing backslash `\`.  
MDL will join them back together before writing the final `.mcfunction`.

Example:

```mdl
// Multi-line Demo
pack "Multi-line Demo";

namespace "demo";

function "multiline" {
    tellraw @a \
        {"text":"This text is really, really long so we split it",\
         "color":"gold"};
}
```

When compiled, the function is a single line:

```mcfunction
tellraw @a {"text":"This text is really, really long so we split it","color":"gold"}
```

---

## ๐ŸŽฏ **MODERN** example (control structures + variables + expressions)

```mdl
// modern_pack.mdl - modern example for Minecraft Datapack Language
pack "Modern Pack" description "Modern example datapack" pack_format 82;

namespace "example";

// Number variables with expressions
var num counter = 0;
var num health = 20;
var num level = 1;
var num experience = 0;

function "inner" {
    say [example:inner] This is the inner function;
    tellraw @a {"text":"Running inner","color":"yellow"};
    counter = counter + 1;
}

function "hello" {
    say [example:hello] Outer says hi;
    function example:inner;
    tellraw @a {"text":"Back in hello","color":"aqua"};
    
    // Variable operations with expressions
    health = health + 5;
    level = level + 1;
    experience = $level$ * 100 + $counter$;
    
    // Variable substitution
    say Health: $health$;
    say Level: $level$;
    say Experience: $experience$;
    
    // Full control structures
    if "$health$ > 15" {
        say High health!;
        effect give @s minecraft:strength 10 1;
    } else if "$level$ > 5" {
        say High level!;
        effect give @s minecraft:speed 10 1;
    } else {
        say Normal stats;
        effect give @s minecraft:jump_boost 10 0;
    }
    
    // While loop with method selection
    while "$counter$ < 5" {
        say Counter: $counter$;
        counter = counter + 1;
    }
    
    // Expression in condition
    if "$experience$ > $level$ * 50" {
        say High experience for level!;
    }
}

// Hook the function into load and tick
on_load "example:hello";
on_tick "example:hello";

// Second namespace with a cross-namespace call
namespace "util";

var num helper_count = 0;
var num total_help = 0;

function "helper" {
    say [util:helper] Helping out...;
    helper_count = helper_count + 1;
    total_help = $helper_count$ * 10;
    say Helper count: $helper_count$;
    say Total help: $total_help$;
}

function "boss" {
    say [util:boss] Calling example:hello then util:helper;
    function example:hello;
    function util:helper;
}

// Run boss every tick as well
on_tick "util:boss";

// Function tag examples
tag function "minecraft:load" {
    add "example:hello";
}

tag function "minecraft:tick" {
    add "example:hello";
    add "util:boss";
}

// Data tag examples across registries
tag item "example:swords" {
    add "minecraft:diamond_sword";
    add "minecraft:netherite_sword";
}

tag block "example:glassy" {
    add "minecraft:glass";
    add "minecraft:tinted_glass";
}
```

### What this demonstrates
- **Nested-like function composition** (`function example:inner` inside `function "hello"`).
- **Multiple namespaces** (`example`, `util`) calling each other with fully-qualified IDs.
- **Lifecycle hooks** (`on_load`, `on_tick`) on both `example:hello` and `util:boss`.
- **Function tags** to participate in vanilla tags (`minecraft:load`, `minecraft:tick`).
- **Data tags** (`item`, `block`) in addition to function tags.
- **Number variables** with `$variable$` substitution.
- **Expressions** with arithmetic operations and variable substitution.
- **Full control structures** - `if/else if/else`, `while` loops with method selection.
- **Modern syntax** with curly braces and semicolons.
- **Variable optimization** - automatic load function generation.

---

## ๐Ÿ Python API equivalent

```python
from minecraft_datapack_language import Pack

def build_pack():
    p = Pack(name="Modern Pack",
             description="Modern example datapack",
             pack_format=82)

    ex = p.namespace("example")
    ex.function("inner",
        'say [example:inner] This is the inner function',
        'tellraw @a {"text":"Running inner","color":"yellow"}'
    )
    ex.function("hello",
        'say [example:hello] Outer says hi',
        'function example:inner',
        'tellraw @a {"text":"Back in hello","color":"aqua"}'
    )

    # Hooks for example namespace
    p.on_load("example:hello")
    p.on_tick("example:hello")

    util = p.namespace("util")
    util.function("helper",
        'say [util:helper] Helping out...'
    )
    util.function("boss",
        'say [util:boss] Calling example:hello then util:helper',
        'function example:hello',
        'function util:helper'
    )

    # Tick hook for util namespace
    p.on_tick("util:boss")

    # Function tags
    p.tag("function", "minecraft:load", values=["example:hello"])
    p.tag("function", "minecraft:tick", values=["example:hello", "util:boss"])

    # Data tags
    p.tag("item",  "example:swords", values=["minecraft:diamond_sword", "minecraft:netherite_sword"])
    p.tag("block", "example:glassy", values=["minecraft:glass", "minecraft:tinted_glass"])

    return p
```

Build it:
```bash
python - <<'PY'
from my_pack_module import build_pack
from minecraft_datapack_language.cli import main as M
# write to dist/ with a wrapper folder name 'mypack'
p = build_pack()
M(['build', '--py-object', 'my_pack_module:build_pack', '-o', 'dist', '--wrapper', 'mypack', '--pack-format', '82'])
PY
```

---

## ๐Ÿ”ง Development System

MDL includes a comprehensive development system that allows you to work with both stable and development versions simultaneously.

### Quick Setup

**Linux/macOS:**
```bash
./scripts/dev_setup.sh
```

**Windows (PowerShell):**
```powershell
.\scripts\dev_setup.ps1
```

### Development Commands

- **`mdl`** - Stable, globally installed version
- **`mdlbeta`** - Local development version for testing changes

### Development Workflow

1. **Make changes** to the code
2. **Rebuild** the development version:
   ```bash
   ./scripts/dev_build.sh
   ```
3. **Test** your changes with `mdlbeta`:
   ```bash
   mdlbeta build --mdl your_file.mdl -o dist
   ```
4. **Compare** with stable version:
   ```bash
   mdl build --mdl your_file.mdl -o dist_stable
   ```

### Testing

**Test the development environment:**
```bash
# Linux/macOS
./scripts/test_dev.sh

# Windows (PowerShell)
.\scripts\test_dev.ps1
```

For more details, see [DEVELOPMENT.md](DEVELOPMENT.md).

## ๐Ÿ”ง VS Code Extension

Get syntax highlighting, error checking, and build commands for `.mdl` files in VS Code, Cursor, and other VS Code-based editors.

### Quick Install

1. **Download from [GitHub Releases](https://github.com/aaron777collins/MinecraftDatapackLanguage/releases)**
2. **Install the `.vsix` file**:
   - Open VS Code/Cursor
   - Go to Extensions (Ctrl+Shift+X)
   - Click "..." โ†’ "Install from VSIX..."
   - Choose the downloaded `.vsix` file

### Features
- **Syntax highlighting** for `.mdl` files
- **Real-time error checking** with error detection
- **Build commands**: `MDL: Build current file` and `MDL: Check Workspace`
- **Workspace validation** for multi-file projects
- **Server function support**: Proper `@a` selector usage for tag-called functions

### Development Setup
```bash
cd vscode-extension/
npm i
# Press F5 to launch the Extension Dev Host
```

---

## ๐Ÿš€ CI & Releases

- **CI** runs on push/PR across Linux/macOS/Windows and uploads artifacts.
- **Release** is triggered by pushing a tag like `v1.0.0` or via the Release workflow manually.
- Versions are derived from git tags via **setuptools-scm**; tag `vX.Y.Z` โ†’ package version `X.Y.Z`.

### Local release helper
```bash
# requires GitHub CLI: gh auth login
./scripts/release.sh patch  "Fixes"
./scripts/release.sh minor  "Features"
./scripts/release.sh major  "Breaking"
./scripts/release.sh v1.2.3 "Exact version"
```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "minecraft-datapack-language",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": null,
    "author": null,
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/cd/da/478945397b1900292859a005ae575a39f2e1aae3d5711fb19bf3cb874a71/minecraft_datapack_language-15.4.23.tar.gz",
    "platform": null,
    "description": "# <img src=\"https://github.com/aaron777collins/MinecraftDatapackLanguage/raw/main/icons/icon-128.png\" width=\"32\" height=\"32\" alt=\"MDL Icon\"> Minecraft Datapack Language (MDL)\n\nA **modern JavaScript-style compiler** that lets you write Minecraft datapacks with **real control structures, variables, and expressions** that actually work.\n\n\ud83d\udcd6 **[View Full Documentation](https://www.mcmdl.com/)** - Complete guides, examples, and API reference  \n\ud83d\udce6 **[View on PyPI](https://pypi.org/project/minecraft-datapack-language/)** - Download and install from PyPI  \n\ud83d\udd27 **[VS Code Extension](https://marketplace.visualstudio.com/items?itemName=mdl.minecraft-datapack-language)** - Syntax highlighting, IntelliSense, and snippets\n\n![CI](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/CI/badge.svg)\n![Test Examples](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/Test%20Examples/badge.svg)\n![Documentation](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/Build%20and%20Deploy%20Documentation/badge.svg)\n![PyPI](https://img.shields.io/pypi/v/minecraft-datapack-language?style=flat-square)\n![Release](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/Release/badge.svg)\n\n## \ud83c\udfaf **MODERN** JavaScript-Style MDL Language\n\n**MDL uses a modern JavaScript-style language format** with **real control structures, variables, and expressions**:\n\n### \u2728 **MODERN** Features\n- **\ud83c\udfaf JavaScript-style syntax** with curly braces `{}` and semicolons `;`\n- **\ud83d\udcdd Modern comments** using `//` and `/* */`\n- **\ud83d\udd22 Number variables** with `var num` type (stored in scoreboards)\n- **\ud83d\udd04 Full control structures** including `if/else if/else`, `while` loops with method selection\n- **\ud83d\udcb2 Variable substitution** with `$variable$` syntax\n- **\ud83e\uddee Expressions** with arithmetic operations (`+`, `-`, `*`, `/`)\n- **\ud83d\udce6 Namespace system** for modular code organization\n- **\ud83c\udfa8 VS Code extension** with full IntelliSense and snippets\n- **\ud83e\uddea Comprehensive testing** with E2E validation\n- **\ud83d\udcda Extensive documentation** with examples for every feature\n\n### \ud83c\udfd7\ufe0f Core Features\n- \u2705 **Modern pack format 82** by default for latest Minecraft features\n- \u2705 **JavaScript-style syntax** with curly braces and semicolons\n- \u2705 **Real control structures** - `if/else if/else`, `while` loops with recursion/schedule methods\n- \u2705 **Number variables** stored in scoreboards with `$variable$` substitution\n- \u2705 **Expressions** with arithmetic operations and variable substitution\n- \u2705 **Multi-file projects** with automatic merging and dependency resolution\n- \u2705 **Variable optimization** - automatic load function generation for initialization\n- \u2705 **Selector optimization** - proper `@a` usage for system commands\n- \u2705 **Easy hooks** into `minecraft:tick` and `minecraft:load` via function tags\n- \u2705 **Tag support** for `function`, `item`, `block`, `entity_type`, `fluid`, and `game_event`\n\n> **Note**: Version 12.0+ uses **pack_format 82** by default for the modern JavaScript-style syntax.\n\n---\n\n## \ud83d\ude80 Install\n\n### Option A \u2014 from PyPI (recommended for users)\nGlobal, isolated CLI via **pipx**:\n```bash\npython3 -m pip install --user pipx\npython3 -m pipx ensurepath    # reopen terminal\npipx install minecraft-datapack-language\n\nmdl --help\n```\n\nVirtualenv (if you prefer):\n```bash\npython3 -m venv .venv\nsource .venv/bin/activate      # Windows: .\\.venv\\Scripts\\Activate.ps1\npip install minecraft-datapack-language\n```\n\n### Option B \u2014 from source (for contributors)\n```bash\n# inside the repo\npython -m pip install -e .\n```\n\n---\n\n## \ud83d\udd04 Update\n\n- **pipx**: `pipx upgrade minecraft-datapack-language`  \n- **pip (venv)**: `pip install -U minecraft-datapack-language`  \n- Pin a version: `pipx install \"minecraft-datapack-language==<version>\"` (replace `<version>` with desired version)\n\n---\n\n## \ud83d\udcbb CLI\n\n### Modern JavaScript-style MDL (v15.0+)\n```bash\n# Build JavaScript-style MDL files\nmdl build --mdl my_pack/mypack.mdl -o dist --wrapper mypack\nmdl check my_pack/mypack.mdl\n\n# Validate generated mcfunction files\nmdl check my_pack/mypack.mdl\n\n# Multi-file projects\nmdl build --mdl my_pack/ -o dist      # Build entire directory\nmdl build --mdl \"file1.mdl file2.mdl\" -o dist  # Build specific files\n\n# Create new projects\nmdl new my_awesome_pack\n```\n\n### \ud83d\udc1b **Comprehensive Error Handling**\n\nMDL provides detailed error reporting with exact locations and helpful suggestions:\n\n```bash\n# Check for errors with detailed output\nmdl check my_pack.mdl --verbose\n```\n\n**Example Error Output:**\n```\nError 1: MDLSyntaxError in test.mdl:15:8\nMissing closing brace for if statement\nContext:\n  13:   if (score > 10) {\n  14:     say \"High score!\"\n  15:     score = 0\n  16:   }\n\nSuggestion: Add closing brace '}' after line 15\n\nError 2: MDLLexerError in test.mdl:22:12\nUnterminated string literal\nContext:\n  20:   say \"Hello world\n  21:   score = 10\n  22:   say \"Goodbye\n\nSuggestion: Add closing quote '\"' at the end of line 20\n```\n\n**Error Features:**\n- \u2705 **Exact Location**: Line and column numbers for precise error location\n- \u2705 **Context Lines**: Shows surrounding code for better debugging\n- \u2705 **Helpful Suggestions**: Specific fix recommendations\n- \u2705 **Multiple Error Collection**: Reports all errors, not just the first\n- \u2705 **Error Types**: Syntax, Lexer, Parser, Validation, File, Build, and Configuration errors\n\n### Comments in MDL\nMDL supports modern JavaScript-style comments:\n```javascript\n// Single-line comments\n/* Multi-line comments */\n\npack \"My Pack\" {\n    function example() {\n        // This comment will be properly converted to mcfunction\n        say Hello World!;\n    }\n}\n```\n\nGenerated mcfunction files will have proper `#` comments:\n```mcfunction\n# This is a generated comment\nsay Hello World!\n```\n\n### Build a whole folder of `.mdl` files\n```bash\nmdl build --mdl src/ -o dist\n# Recursively parses src/**/*.mdl, merges into one pack (errors on duplicate functions).\n# Only the first file should have a pack declaration - all others are modules.\n```\n\n### Build multiple specific `.mdl` files\n```bash\nmdl build --mdl \"src/core.mdl src/features.mdl src/ui.mdl\" -o dist\n# Parses multiple specific files and merges them into one datapack.\n# Only the first file should have a pack declaration - all others are modules.\n```\n\n### Validate a folder (JSON diagnostics)\n```bash\nmdl check --json src/\n```\n\n---\n\n## \ud83d\udcdd Quick Start - **MODERN** MDL\n\nCreate your first modern MDL project:\n\n```mdl\n// modern_pack.mdl\npack \"Modern Pack\" description \"A modern example\" pack_format 82;\n\nnamespace \"example\";\n\n// Number variables with expressions\nvar num counter = 0;\nvar num health = 20;\nvar num level = 1;\nvar num experience = 0;\n\nfunction \"init\" {\n    say Initializing...;\n    counter = 0;\n    health = 20;\n    level = 1;\n    experience = 0;\n}\n\nfunction \"tick\" {\n    counter = counter + 1;\n    \n    // Full if/else if/else control structure\n    if \"$health$ < 10\" {\n        say Health is low!;\n        health = health + 5;\n        effect give @a minecraft:regeneration 10 1;\n    } else if \"$level$ > 5\" {\n        say High level player!;\n        effect give @a minecraft:strength 10 1;\n    } else {\n        say Normal player;\n        effect give @a minecraft:speed 10 0;\n    }\n    \n    // Variable substitution in strings\n    say Counter: $counter$;\n    \n    // While loop with method selection\n    while \"$counter$ < 10\" {\n        counter = $counter$ + 1;\n        say Counter: $counter$;\n    }\n    \n    // Expressions with arithmetic\n    experience = $level$ * 100 + $counter$;\n    say Experience: $experience$;\n}\n\n// Lifecycle hooks\non_load \"example:init\";\non_tick \"example:tick\";\n```\n\nBuild and test:\n```bash\nmdl build --mdl modern_pack.mdl -o dist\n# \u2192 dist/modern_pack/... and dist/modern_pack.zip\n```\n\n---\n\n## \ud83d\udcc1 Multi-file Support\n\nMDL supports building datapacks from multiple `.mdl` files. This is useful for organizing large projects into logical modules.\n\n### How it works\n- **Directory scanning**: When you pass a directory to `--mdl`, MDL recursively finds all `.mdl` files\n- **File merging**: Each file is parsed into a `Pack` object, then merged into a single datapack\n- **Conflict resolution**: Duplicate function names within the same namespace will cause an error\n- **Pack metadata**: Only the **first file** should have a pack declaration (name, description, format)\n- **Module files**: Subsequent files should **not** have pack declarations - they are treated as modules\n- **Single file compilation**: When compiling a single file, it **must** have a pack declaration\n\n### Best practices\n- **One pack declaration per project**: Only the **first file** should have a pack declaration\n- **Module files**: All other files should **not** have pack declarations - they are treated as modules\n- **Single file requirement**: When compiling a single file, it **must** have a pack declaration\n- **Organize by namespace**: Consider splitting files by namespace or feature\n- **Use descriptive filenames**: `core.mdl`, `combat.mdl`, `ui.mdl` etc.\n- **Avoid conflicts**: Ensure function names are unique within each namespace\n\n### Example project structure\n```\nmy_datapack/\n\u251c\u2500\u2500 core.mdl          # \u2705 HAS pack declaration\n\u251c\u2500\u2500 combat/\n\u2502   \u251c\u2500\u2500 weapons.mdl   # \u274c NO pack declaration (module)\n\u2502   \u2514\u2500\u2500 armor.mdl     # \u274c NO pack declaration (module)\n\u251c\u2500\u2500 ui/\n\u2502   \u2514\u2500\u2500 hud.mdl       # \u274c NO pack declaration (module)\n\u2514\u2500\u2500 data/\n    \u2514\u2500\u2500 recipes.mdl   # \u274c NO pack declaration (module)\n```\n\n**Important**: Only `core.mdl` should have a `pack \"Name\"` declaration. All other files are modules that merge into the main pack.\n\n### Usage Examples\n\n**Build from directory:**\n```bash\nmdl build --mdl my_datapack/ -o dist\n```\n\n**Build from specific files:**\n```bash\nmdl build --mdl \"core.mdl combat.mdl ui.mdl\" -o dist\n```\n\n**Check entire project:**\n```bash\nmdl check my_datapack/\n```\n\n**Check with verbose output:**\n```bash\nmdl build --mdl my_datapack/ -o dist --verbose\n```\n\n### Complete Multi-File Example\n\nHere's a complete example showing how to organize a datapack across multiple files:\n\n**`core.mdl`** (main file with pack declaration):\n```mdl\n// core.mdl - Main pack and core systems\npack \"Adventure Pack\" description \"Multi-file example datapack\" pack_format 82;\n\nnamespace \"core\";\n\n// Number variables with expressions\nvar num system_version = 1;\nvar num player_count = 0;\nvar num total_experience = 0;\n\nfunction \"init\" {\n    say [core:init] Initializing Adventure Pack...;\n    tellraw @a {\"text\":\"Adventure Pack loaded!\",\"color\":\"green\"};\n    system_version = 1;\n    player_count = 0;\n    total_experience = 0;\n}\n\nfunction \"tick\" {\n    say [core:tick] Core systems running...;\n    execute as @a run particle minecraft:end_rod ~ ~ ~ 0.1 0.1 0.1 0.01 1;\n    player_count = player_count + 1;\n    \n    // Control structure example\n    if \"$player_count$ > 10\" {\n        say Many players online!;\n        effect give @a minecraft:glowing 5 0;\n    }\n}\n\n// Hook into vanilla lifecycle\non_load \"core:init\";\non_tick \"core:tick\";\n```\n\n**`combat/weapons.mdl`** (combat module):\n```mdl\n// combat/weapons.mdl - Weapon-related functions\nnamespace \"combat\";\n\nvar num weapon_damage = 10;\nvar num critical_chance = 5;\n\nfunction \"weapon_effects\" {\n    say [combat:weapon_effects] Applying weapon effects...;\n    execute as @a[nbt={SelectedItem:{id:'minecraft:diamond_sword'}}] run effect give @s minecraft:strength 1 0 true;\n    weapon_damage = weapon_damage + 2;\n    \n    // Expression example\n    critical_chance = $weapon_damage$ / 2;\n}\n\nfunction \"update_combat\" {\n    function core:tick;\n    function combat:weapon_effects;\n}\n```\n\n**`combat/armor.mdl`** (armor module):\n```mdl\n// combat/armor.mdl - Armor-related functions\nnamespace \"combat\";\n\nvar num armor_bonus = 5;\nvar num defense_rating = 0;\n\nfunction \"armor_bonus\" {\n    say [combat:armor_bonus] Checking armor bonuses...;\n    execute as @a[nbt={Inventory:[{Slot:103b,id:\"minecraft:diamond_helmet\"}]}] run effect give @s minecraft:resistance 1 0 true;\n    armor_bonus = armor_bonus + 1;\n    \n    // Expression with multiple variables\n    defense_rating = $armor_bonus$ * 2 + 10;\n}\n\nfunction \"update_armor\" {\n    function combat:armor_bonus;\n}\n```\n\n**`ui/hud.mdl`** (UI module):\n```mdl\n// ui/hud.mdl - User interface functions\nnamespace \"ui\";\n\nvar num hud_version = 1;\nvar num display_counter = 0;\n\nfunction \"show_hud\" {\n    say [ui:show_hud] Updating HUD...;\n    title @a actionbar {\"text\":\"Adventure Pack Active\",\"color\":\"gold\"};\n    hud_version = hud_version + 1;\n    \n    // While loop example\n    while \"$display_counter$ < 5\" {\n        display_counter = $display_counter$ + 1;\n        say HUD update: $display_counter$;\n    }\n}\n\nfunction \"update_ui\" {\n    function ui:show_hud;\n    function combat:update_combat;\n    function combat:update_armor;\n}\n```\n\n**Project structure:**\n```\nadventure_pack/\n\u251c\u2500\u2500 core.mdl              # \u2705 HAS pack declaration\n\u251c\u2500\u2500 combat/\n\u2502   \u251c\u2500\u2500 weapons.mdl       # \u274c NO pack declaration (module)\n\u2502   \u2514\u2500\u2500 armor.mdl         # \u274c NO pack declaration (module)\n\u2514\u2500\u2500 ui/\n    \u2514\u2500\u2500 hud.mdl           # \u274c NO pack declaration (module)\n```\n\n**Build the project:**\n```bash\nmdl build --mdl adventure_pack/ -o dist --verbose\n```\n\nThis will create a datapack with:\n- **Core systems** (initialization and tick functions)\n- **Combat features** (weapon and armor effects)\n- **UI elements** (HUD display)\n- **Cross-module calls** (UI calls combat functions)\n- **Variable optimization** (automatic load function generation)\n\n### CLI Options for Multi-file Builds\n\n- `--mdl <path>`: Path to `.mdl` file, directory, or space-separated file list\n- `--src <path>`: Alias for `--mdl` (same functionality)\n- `-o, --out <dir>`: Output directory for the built datapack\n- `--wrapper <name>`: Custom wrapper folder/zip name (default: first namespace or pack name slug)\n- `--pack-format <N>`: Minecraft pack format (default: 82 for modern syntax)\n- `-v, --verbose`: Show detailed processing information including file merging\n- `--py-module <path>`: Alternative: build from Python module with `create_pack()` function\n\n### Error Handling\n\n- **Missing pack declaration**: Single files must have a pack declaration\n- **Duplicate pack declarations**: Only the first file in a multi-file project should have a pack declaration\n- **Function conflicts**: Duplicate function names within the same namespace will cause an error\n- **Clear error messages**: Errors include file paths and line numbers for easy debugging\n\n---\n\n## \ud83c\udfaf **Explicit Scope System**\n\nMDL features a powerful **explicit scope system** that makes variable access clear and unambiguous. Each variable access must specify its scope, eliminating hidden state and making code more readable.\n\n### **Variable Declaration Scopes**\n\n```mdl\n// Player-specific variable (defaults to @s in execution context)\nvar num playerScore = 0;\n\n// Server-wide variable (stored on server armor stand)\nvar num globalCounter scope<global> = 0;\n\n// Team-specific variable\nvar num teamScore scope<@a[team=red]> = 0;\n\n// Custom entity variable\nvar num entityData scope<@e[type=armor_stand,tag=special,limit=1]> = 0;\n```\n\n### **Variable Access with Explicit Scopes**\n\n```mdl\n// Each variable access must specify the scope\nplayerScore<@s> = 42;                    // Player scope\nglobalCounter<global> = 100;             // Global scope\nteamScore<@a[team=red]> = 5;            // Team scope\nentityData<@e[type=armor_stand,tag=special,limit=1]> = 10; // Custom entity\n```\n\n### **Explicit Scopes in Conditions**\n\n**NEW!** MDL now supports explicit scope selectors in if/while conditions, allowing you to override declared variable scopes:\n\n```mdl\nfunction \"check_scores\" {\n    // Check current player's score\n    if \"$playerScore<@s>$ > 10\" {\n        say \"Your score is high!\";\n    }\n    \n    // Check global counter\n    if \"$globalCounter<global>$ > 100\" {\n        say \"Global milestone reached!\";\n    }\n    \n    // Check another player's score\n    if \"$playerScore<@p[name=Steve]>$ > 20\" {\n        say \"Steve has a good score!\";\n    }\n    \n    // Check team score\n    if \"$teamScore<@a[team=red]>$ > 50\" {\n        say \"Red team is winning!\";\n    }\n    \n    // Use explicit scopes in while loops too\n    while \"$globalCounter<global>$ < 10\" {\n        globalCounter<global> = globalCounter<global> + 1;\n        say \"Counter: $globalCounter$\";\n    }\n}\n```\n\n**Benefits:**\n- **Override declared scopes**: Use different scopes than what was declared\n- **Check other entities**: Compare scores across different players/teams\n- **Flexible conditions**: Mix and match scopes as needed\n- **Clear intent**: Explicit scope makes code more readable and debuggable\n\n### **Scope Mapping**\n\nMDL maps scopes to Minecraft selectors:\n\n| MDL Scope | Minecraft Selector | Description |\n|-----------|-------------------|-------------|\n| `scope<global>` | `@e[type=armor_stand,tag=mdl_server,limit=1]` | Server-wide storage |\n| `scope<@s>` | `@s` | Current player |\n| `scope<@a>` | `@a` | All players |\n| `scope<@a[team=red]>` | `@a[team=red]` | Red team players |\n| `scope<@e[type=armor_stand,tag=something,limit=1]>` | `@e[type=armor_stand,tag=something,limit=1]` | Custom entity |\n\n---\n\n## \ud83c\udfaf **Advanced Multi-File Examples with Namespaces**\n\n### **Modern Namespace System**\n\nMDL's namespace system allows you to organize code across multiple files with proper separation:\n\n**`game.mdl`** - Core Game Logic:\n```mdl\npack \"multi_game\" \"A multi-file game example\" 82;\n\nnamespace \"game\";\n\nvar num player_score = 0;\nvar num game_timer = 0;\nvar num health = 20;\n\nfunction \"main\" {\n    // If-else if-else chain\n    if \"$health$ < 10\" {\n        say \"Health is low: $health$\";\n        health = $health$ + 5;\n    } else if \"$health$ > 15\" {\n        say \"Health is good: $health$\";\n    } else {\n        say \"Health is moderate: $health$\";\n    }\n    \n    // While loop with counter\n    while \"$game_timer$ < 5\" {\n        game_timer = $game_timer$ + 1;\n        say \"Game Timer: $game_timer$\";\n    }\n}\n\nfunction \"score_update\" {\n    player_score = $player_score$ + 10;\n    say \"Score updated: $player_score$\";\n}\n\non_tick \"game:main\";\n```\n\n**`ui.mdl`** - User Interface:\n```mdl\nnamespace \"ui\";\n\nvar num menu_state = 0;\nvar num selected_option = 1;\n\nfunction \"main\" {\n    // Show menu based on state\n    if \"$menu_state$ == 0\" {\n        say \"=== Main Menu ===\";\n        say \"1. Start Game\";\n        say \"2. Options\";\n        say \"3. Exit\";\n    }\n    \n    // Handle selection\n    if \"$selected_option$ == 1\" {\n        say \"Starting game...\";\n    } else if \"$selected_option$ == 2\" {\n        say \"Opening options...\";\n    } else if \"$selected_option$ == 3\" {\n        say \"Exiting...\";\n    }\n}\n\nfunction \"button_handler\" {\n    var num button_id = 0;\n    \n    if \"$button_id$ == 1\" {\n        selected_option = 1;\n        say \"Option 1 selected\";\n    } else if \"$button_id$ == 2\" {\n        selected_option = 2;\n        say \"Option 2 selected\";\n    }\n}\n\non_load \"ui:main\";\n```\n\n**`combat.mdl`** - Combat System:\n```mdl\nnamespace \"combat\";\n\nvar num enemy_count = 5;\nvar num damage = 0;\n\nfunction \"main\" {\n    var num total_damage = 0;\n    total_damage = $damage$ * 2;\n    \n    if \"$total_damage$ > 20\" {\n        say \"Critical hit! Damage: $total_damage$\";\n    } else {\n        say \"Normal hit. Damage: $total_damage$\";\n    }\n    \n    // Variable substitution in tellraw\n    tellraw @a [{\"text\":\"Enemy Count: \"},{\"score\":{\"name\":\"@a\",\"objective\":\"enemy_count\"}}];\n}\n\non_tick \"combat:main\";\n```\n\n### **Build and Generated Structure**\n\n```bash\n# Build all files together\nmdl build --mdl . -o dist\n\n# Or build specific files\nmdl build --mdl \"game.mdl ui.mdl combat.mdl\" -o dist\n```\n\n**Generated Structure:**\n```\ndist/\n\u251c\u2500\u2500 data/\n\u2502   \u251c\u2500\u2500 minecraft/tags/function/\n\u2502   \u2502   \u251c\u2500\u2500 load.json    # Contains all load functions\n\u2502   \u2502   \u2514\u2500\u2500 tick.json    # Contains all tick functions\n\u2502   \u251c\u2500\u2500 game/            # game.mdl namespace\n\u2502   \u2502   \u2514\u2500\u2500 function/\n\u2502   \u2502       \u251c\u2500\u2500 main.mcfunction\n\u2502   \u2502       \u2514\u2500\u2500 score_update.mcfunction\n\u2502   \u251c\u2500\u2500 ui/              # ui.mdl namespace\n\u2502   \u2502   \u2514\u2500\u2500 function/\n\u2502   \u2502       \u251c\u2500\u2500 main.mcfunction\n\u2502   \u2502       \u2514\u2500\u2500 button_handler.mcfunction\n\u2502   \u2514\u2500\u2500 combat/          # combat.mdl namespace\n\u2502       \u2514\u2500\u2500 function/\n\u2502           \u2514\u2500\u2500 main.mcfunction\n\u2514\u2500\u2500 pack.mcmeta\n```\n\n### **Key Benefits of Namespace System**\n\n- \u2705 **No function name conflicts** - Each namespace is completely separate\n- \u2705 **Modular development** - Work on different features in separate files\n- \u2705 **Automatic merging** - All variables and functions are combined intelligently\n- \u2705 **Proper initialization** - Variables are automatically set up in load functions\n- \u2705 **Clean organization** - Each module has its own directory structure\n- \u2705 **Easy maintenance** - Update individual modules without affecting others\n\n### **Complete Example Project**\n\nCheck out the `examples/multi_file_example/` directory for a complete working example with:\n- Multiple namespaces (`test`, `other`, `ui`)\n- Various control structures and expressions\n- Comprehensive documentation\n- Ready-to-build files\n\n---\n\n## \ud83d\udcdd The **MODERN** `.mdl` Language\n\n### Grammar you can rely on (based on the parser)\n- **pack header** (required once):\n  ```mdl\n  pack \"Name\" [description \"Desc\"] [pack_format N];\n  ```\n- **namespace** (selects a namespace for following blocks):\n  ```mdl\n  namespace \"example\";\n  ```\n- **number variable declarations** (only `num` type supported):\n  ```mdl\n  var num counter = 0;\n  var num health = 20;\n  var num level = 1;\n  ```\n- **function** (curly braces + semicolons):\n  ```mdl\n  function \"hello\" {\n      say hi;\n      tellraw @a {\"text\":\"ok\",\"color\":\"green\"};\n  }\n  ```\n- **full conditional blocks** (if/else if/else statements):\n  ```mdl\n  function \"conditional\" {\n      if \"$health$ < 10\" {\n          say Health is low!;\n          effect give @s minecraft:glowing 5 1;\n      } else if \"$level$ > 5\" {\n          say High level player!;\n          effect give @s minecraft:speed 5 1;\n      } else {\n          say Normal player;\n          effect give @s minecraft:jump_boost 5 0;\n      }\n  }\n  ```\n- **while loops** (repetitive execution with method selection):\n  ```mdl\n  function \"countdown\" {\n      var num counter = 5;\n      while \"$counter$ > 0\" {\n          say Counter: $counter$;\n          counter = counter - 1;\n      }\n      \n      // Schedule method for performance\n      counter = 10;\n      while \"$counter$ > 0\" method=\"schedule\" {\n          say Schedule counter: $counter$;\n          counter = $counter$ - 1;\n      }\n  }\n  ```\n- **expressions** (arithmetic operations):\n  ```mdl\n  function \"expressions\" {\n      var num a = 10;\n      var num b = 5;\n      var num result = $a$ + $b$ * 2;\n      say Result: $result$;\n  }\n  ```\n- **function calls** (one function invoking another with fully qualified ID):\n  ```mdl\n  function \"outer\" {\n      say I will call another function;\n      function example:hello;\n  }\n  ```\n- **hooks** (namespaced ids required):\n  ```mdl\n  on_load \"example:hello\";\n  on_tick \"example:hello\";\n  ```\n- **tags** (supported registries: `function`, `item`, `block`, `entity_type`, `fluid`, `game_event`):\n  ```mdl\n  tag function \"minecraft:tick\" {\n      add \"example:hello\";\n  }\n  ```\n- **comments** start with `//` or `/* */`. Hashes inside **quoted strings** are preserved.\n- **whitespace**: empty lines are ignored; **explicit block boundaries** using curly braces `{` and `}`; **statement termination** using semicolons `;`.\n\n> Inside a function block, **every non-empty line** is emitted almost verbatim as a Minecraft command. Comments are stripped out and multi-line commands are automatically wrapped. See below for details.\n\n### Comments\n\nMDL supports modern JavaScript-style comments:\n\n- **Full-line comments** (a line starting with `//`) are ignored by the parser.\n- **Block comments** (`/* */`) are supported for multi-line comments.\n- **Inline `#` characters** are preserved inside function bodies, so you can still use them the way `mcfunction` normally allows.\n\nExample:\n\n```mdl\n// Comment Demo - Testing comments\npack \"Comment Demo\" description \"Testing comments\";\n\nnamespace \"demo\";\n\nfunction \"comments\" {\n    // This whole line is ignored by MDL\n    say Hello; // This inline comment is preserved\n    tellraw @a {\"text\":\"World\",\"color\":\"blue\"}; // Inline too!\n    \n    /* This is a block comment\n       that spans multiple lines\n       and is ignored by the parser */\n}\n```\n\nWhen compiled, the resulting function looks like:\n\n```mcfunction\nsay Hello # This inline comment is preserved\ntellraw @a {\"text\":\"World\",\"color\":\"blue\"} # Inline too!\n```\n\nNotice how the full-line `//` and block comments never make it into the `.mcfunction`, but the inline ones do.\n\n---\n\n### **MODERN** Variables and Data Types\n\nMDL supports **number variables** with **expressions and arithmetic operations**:\n\n#### Number Variables (`num`)\n```mdl\nvar num counter = 0;\nvar num health = 20;\nvar num experience = 100;\n\n// Arithmetic operations\ncounter = counter + 1;\nhealth = health - 5;\nexperience = experience * 2;\n\n// Expressions with multiple variables\nvar num total = $health$ + $experience$;\nvar num average = $total$ / 2;\n\n// Variable substitution in strings\nsay Health: $health$;\nsay Experience: $experience$;\nsay Total: $total$;\n```\n\n**Variable Substitution**: Use `$variable_name$` to read values from scoreboards in strings and conditions.\n\n**Expressions**: Support for arithmetic operations (`+`, `-`, `*`, `/`) with proper order of operations.\n\n### **MODERN** Control Flow\n\nMDL supports full conditional blocks and loops for control flow.\n\n#### Conditional Blocks\n\nMDL supports complete if/else if/else statements for conditional execution:\n\n```mdl\nfunction \"conditional_example\" {\n    var num player_level = 15;\n    var num player_health = 8;\n    var num player_experience = 1000;\n    \n    if \"$player_level$ >= 10\" {\n        if \"$player_health$ < 10\" {\n            say Advanced player with low health!;\n            effect give @s minecraft:regeneration 10 1;\n            player_health = $player_health$ + 10;\n        } else {\n            say Advanced player with good health;\n            effect give @s minecraft:strength 10 1;\n        }\n    } else if \"$player_level$ >= 5\" {\n        say Intermediate player;\n        effect give @s minecraft:speed 10 0;\n    } else {\n        say Beginner player;\n        effect give @s minecraft:jump_boost 10 0;\n    }\n    \n    // Expression in condition\n    if \"$player_experience$ > $player_level$ * 100\" {\n        say High experience for level!;\n    }\n}\n```\n\n**Rules:**\n- Conditions use `$variable$` syntax for variable substitution\n- **Explicit block boundaries**: Conditional blocks use curly braces `{` and `}`\n- **Statement termination**: All commands must end with semicolons `;`\n- You can have multiple `else if` blocks\n- The `else` block is optional\n- Conditional blocks are compiled to separate functions and called with `execute` commands\n- **Proper logic**: `else if` blocks only execute if previous conditions were false\n- **Expressions in conditions**: Support for arithmetic operations in conditions\n\n#### While Loops\n\nMDL supports while loops with method selection for repetitive execution:\n\n```mdl\nfunction \"while_example\" {\n    var num counter = 5;\n    \n    // Default recursion method (immediate execution)\n    while \"$counter$ > 0\" {\n        say \"Counter: $counter$\";\n        counter = $counter$ - 1;\n    }\n    \n    // Schedule method (spreads across ticks for performance)\n    counter = 10;\n    while \"$counter$ > 0\" method=\"schedule\" {\n        say \"Schedule counter: $counter$\";\n        counter = $counter$ - 1;\n    }\n    \n    // Expression in loop condition\n    var num max_count = 5;\n    counter = 0;\n    while \"$counter$ < $max_count$ * 2\" {\n        say \"Expression counter: $counter$\";\n        counter = $counter$ + 1;\n    }\n}\n```\n\n**Rules:**\n- Conditions use `$variable$` syntax for variable substitution\n- **Explicit block boundaries**: While loops use curly braces `{` and `}`\n- **Statement termination**: All commands must end with semicolons `;`\n- While loops continue until the condition becomes false\n- **Method Selection**: Choose `method=\"recursion\"` (default) or `method=\"schedule\"`\n- **Recursion method**: Executes all iterations immediately (good for small loops)\n- **Schedule method**: Spreads iterations across ticks (better for long loops, prevents lag)\n- **Important**: Ensure your loop body modifies the condition to avoid infinite loops\n- **Expressions in conditions**: Support for arithmetic operations in loop conditions\n\n**Implementation**: While loops generate separate function files with proper recursive calls to continue execution until the condition becomes false.\n\n---\n\n### Multi-line Commands\n\nLong JSON commands can be split across multiple lines with a trailing backslash `\\`.  \nMDL will join them back together before writing the final `.mcfunction`.\n\nExample:\n\n```mdl\n// Multi-line Demo\npack \"Multi-line Demo\";\n\nnamespace \"demo\";\n\nfunction \"multiline\" {\n    tellraw @a \\\n        {\"text\":\"This text is really, really long so we split it\",\\\n         \"color\":\"gold\"};\n}\n```\n\nWhen compiled, the function is a single line:\n\n```mcfunction\ntellraw @a {\"text\":\"This text is really, really long so we split it\",\"color\":\"gold\"}\n```\n\n---\n\n## \ud83c\udfaf **MODERN** example (control structures + variables + expressions)\n\n```mdl\n// modern_pack.mdl - modern example for Minecraft Datapack Language\npack \"Modern Pack\" description \"Modern example datapack\" pack_format 82;\n\nnamespace \"example\";\n\n// Number variables with expressions\nvar num counter = 0;\nvar num health = 20;\nvar num level = 1;\nvar num experience = 0;\n\nfunction \"inner\" {\n    say [example:inner] This is the inner function;\n    tellraw @a {\"text\":\"Running inner\",\"color\":\"yellow\"};\n    counter = counter + 1;\n}\n\nfunction \"hello\" {\n    say [example:hello] Outer says hi;\n    function example:inner;\n    tellraw @a {\"text\":\"Back in hello\",\"color\":\"aqua\"};\n    \n    // Variable operations with expressions\n    health = health + 5;\n    level = level + 1;\n    experience = $level$ * 100 + $counter$;\n    \n    // Variable substitution\n    say Health: $health$;\n    say Level: $level$;\n    say Experience: $experience$;\n    \n    // Full control structures\n    if \"$health$ > 15\" {\n        say High health!;\n        effect give @s minecraft:strength 10 1;\n    } else if \"$level$ > 5\" {\n        say High level!;\n        effect give @s minecraft:speed 10 1;\n    } else {\n        say Normal stats;\n        effect give @s minecraft:jump_boost 10 0;\n    }\n    \n    // While loop with method selection\n    while \"$counter$ < 5\" {\n        say Counter: $counter$;\n        counter = counter + 1;\n    }\n    \n    // Expression in condition\n    if \"$experience$ > $level$ * 50\" {\n        say High experience for level!;\n    }\n}\n\n// Hook the function into load and tick\non_load \"example:hello\";\non_tick \"example:hello\";\n\n// Second namespace with a cross-namespace call\nnamespace \"util\";\n\nvar num helper_count = 0;\nvar num total_help = 0;\n\nfunction \"helper\" {\n    say [util:helper] Helping out...;\n    helper_count = helper_count + 1;\n    total_help = $helper_count$ * 10;\n    say Helper count: $helper_count$;\n    say Total help: $total_help$;\n}\n\nfunction \"boss\" {\n    say [util:boss] Calling example:hello then util:helper;\n    function example:hello;\n    function util:helper;\n}\n\n// Run boss every tick as well\non_tick \"util:boss\";\n\n// Function tag examples\ntag function \"minecraft:load\" {\n    add \"example:hello\";\n}\n\ntag function \"minecraft:tick\" {\n    add \"example:hello\";\n    add \"util:boss\";\n}\n\n// Data tag examples across registries\ntag item \"example:swords\" {\n    add \"minecraft:diamond_sword\";\n    add \"minecraft:netherite_sword\";\n}\n\ntag block \"example:glassy\" {\n    add \"minecraft:glass\";\n    add \"minecraft:tinted_glass\";\n}\n```\n\n### What this demonstrates\n- **Nested-like function composition** (`function example:inner` inside `function \"hello\"`).\n- **Multiple namespaces** (`example`, `util`) calling each other with fully-qualified IDs.\n- **Lifecycle hooks** (`on_load`, `on_tick`) on both `example:hello` and `util:boss`.\n- **Function tags** to participate in vanilla tags (`minecraft:load`, `minecraft:tick`).\n- **Data tags** (`item`, `block`) in addition to function tags.\n- **Number variables** with `$variable$` substitution.\n- **Expressions** with arithmetic operations and variable substitution.\n- **Full control structures** - `if/else if/else`, `while` loops with method selection.\n- **Modern syntax** with curly braces and semicolons.\n- **Variable optimization** - automatic load function generation.\n\n---\n\n## \ud83d\udc0d Python API equivalent\n\n```python\nfrom minecraft_datapack_language import Pack\n\ndef build_pack():\n    p = Pack(name=\"Modern Pack\",\n             description=\"Modern example datapack\",\n             pack_format=82)\n\n    ex = p.namespace(\"example\")\n    ex.function(\"inner\",\n        'say [example:inner] This is the inner function',\n        'tellraw @a {\"text\":\"Running inner\",\"color\":\"yellow\"}'\n    )\n    ex.function(\"hello\",\n        'say [example:hello] Outer says hi',\n        'function example:inner',\n        'tellraw @a {\"text\":\"Back in hello\",\"color\":\"aqua\"}'\n    )\n\n    # Hooks for example namespace\n    p.on_load(\"example:hello\")\n    p.on_tick(\"example:hello\")\n\n    util = p.namespace(\"util\")\n    util.function(\"helper\",\n        'say [util:helper] Helping out...'\n    )\n    util.function(\"boss\",\n        'say [util:boss] Calling example:hello then util:helper',\n        'function example:hello',\n        'function util:helper'\n    )\n\n    # Tick hook for util namespace\n    p.on_tick(\"util:boss\")\n\n    # Function tags\n    p.tag(\"function\", \"minecraft:load\", values=[\"example:hello\"])\n    p.tag(\"function\", \"minecraft:tick\", values=[\"example:hello\", \"util:boss\"])\n\n    # Data tags\n    p.tag(\"item\",  \"example:swords\", values=[\"minecraft:diamond_sword\", \"minecraft:netherite_sword\"])\n    p.tag(\"block\", \"example:glassy\", values=[\"minecraft:glass\", \"minecraft:tinted_glass\"])\n\n    return p\n```\n\nBuild it:\n```bash\npython - <<'PY'\nfrom my_pack_module import build_pack\nfrom minecraft_datapack_language.cli import main as M\n# write to dist/ with a wrapper folder name 'mypack'\np = build_pack()\nM(['build', '--py-object', 'my_pack_module:build_pack', '-o', 'dist', '--wrapper', 'mypack', '--pack-format', '82'])\nPY\n```\n\n---\n\n## \ud83d\udd27 Development System\n\nMDL includes a comprehensive development system that allows you to work with both stable and development versions simultaneously.\n\n### Quick Setup\n\n**Linux/macOS:**\n```bash\n./scripts/dev_setup.sh\n```\n\n**Windows (PowerShell):**\n```powershell\n.\\scripts\\dev_setup.ps1\n```\n\n### Development Commands\n\n- **`mdl`** - Stable, globally installed version\n- **`mdlbeta`** - Local development version for testing changes\n\n### Development Workflow\n\n1. **Make changes** to the code\n2. **Rebuild** the development version:\n   ```bash\n   ./scripts/dev_build.sh\n   ```\n3. **Test** your changes with `mdlbeta`:\n   ```bash\n   mdlbeta build --mdl your_file.mdl -o dist\n   ```\n4. **Compare** with stable version:\n   ```bash\n   mdl build --mdl your_file.mdl -o dist_stable\n   ```\n\n### Testing\n\n**Test the development environment:**\n```bash\n# Linux/macOS\n./scripts/test_dev.sh\n\n# Windows (PowerShell)\n.\\scripts\\test_dev.ps1\n```\n\nFor more details, see [DEVELOPMENT.md](DEVELOPMENT.md).\n\n## \ud83d\udd27 VS Code Extension\n\nGet syntax highlighting, error checking, and build commands for `.mdl` files in VS Code, Cursor, and other VS Code-based editors.\n\n### Quick Install\n\n1. **Download from [GitHub Releases](https://github.com/aaron777collins/MinecraftDatapackLanguage/releases)**\n2. **Install the `.vsix` file**:\n   - Open VS Code/Cursor\n   - Go to Extensions (Ctrl+Shift+X)\n   - Click \"...\" \u2192 \"Install from VSIX...\"\n   - Choose the downloaded `.vsix` file\n\n### Features\n- **Syntax highlighting** for `.mdl` files\n- **Real-time error checking** with error detection\n- **Build commands**: `MDL: Build current file` and `MDL: Check Workspace`\n- **Workspace validation** for multi-file projects\n- **Server function support**: Proper `@a` selector usage for tag-called functions\n\n### Development Setup\n```bash\ncd vscode-extension/\nnpm i\n# Press F5 to launch the Extension Dev Host\n```\n\n---\n\n## \ud83d\ude80 CI & Releases\n\n- **CI** runs on push/PR across Linux/macOS/Windows and uploads artifacts.\n- **Release** is triggered by pushing a tag like `v1.0.0` or via the Release workflow manually.\n- Versions are derived from git tags via **setuptools-scm**; tag `vX.Y.Z` \u2192 package version `X.Y.Z`.\n\n### Local release helper\n```bash\n# requires GitHub CLI: gh auth login\n./scripts/release.sh patch  \"Fixes\"\n./scripts/release.sh minor  \"Features\"\n./scripts/release.sh major  \"Breaking\"\n./scripts/release.sh v1.2.3 \"Exact version\"\n```\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Compile JavaScript-style MDL language or Python API into a Minecraft datapack (1.21+ ready). Features variables, control flow, error handling, and VS Code extension.",
    "version": "15.4.23",
    "project_urls": {
        "Bug Tracker": "https://github.com/aaron777collins/MinecraftDatapackLanguage/issues",
        "Documentation": "https://www.mcmdl.com/docs",
        "Homepage": "https://www.mcmdl.com",
        "Repository": "https://github.com/aaron777collins/MinecraftDatapackLanguage",
        "VS Code Extension": "https://marketplace.visualstudio.com/items?itemName=mdl.minecraft-datapack-language"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b22f96b2966f78bb203c6f3d92de1a567fc28690035fe3d40b04990c8b259161",
                "md5": "47d5f0e29cdbb7cc54f114d40966386a",
                "sha256": "314680239eeda24729766d46c2ccf1d72dce561e41c91f975c0c67b1a8658dd9"
            },
            "downloads": -1,
            "filename": "minecraft_datapack_language-15.4.23-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "47d5f0e29cdbb7cc54f114d40966386a",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 86482,
            "upload_time": "2025-09-02T04:47:51",
            "upload_time_iso_8601": "2025-09-02T04:47:51.640860Z",
            "url": "https://files.pythonhosted.org/packages/b2/2f/96b2966f78bb203c6f3d92de1a567fc28690035fe3d40b04990c8b259161/minecraft_datapack_language-15.4.23-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "cdda478945397b1900292859a005ae575a39f2e1aae3d5711fb19bf3cb874a71",
                "md5": "d8b2f92f7056acbe7104f41409a6caec",
                "sha256": "e148bf517e8e2d1833f3e9798ab63fe2243de04e7145a7e2ee6be449d5c10044"
            },
            "downloads": -1,
            "filename": "minecraft_datapack_language-15.4.23.tar.gz",
            "has_sig": false,
            "md5_digest": "d8b2f92f7056acbe7104f41409a6caec",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 23275172,
            "upload_time": "2025-09-02T04:47:52",
            "upload_time_iso_8601": "2025-09-02T04:47:52.997343Z",
            "url": "https://files.pythonhosted.org/packages/cd/da/478945397b1900292859a005ae575a39f2e1aae3d5711fb19bf3cb874a71/minecraft_datapack_language-15.4.23.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-02 04:47:52",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "aaron777collins",
    "github_project": "MinecraftDatapackLanguage",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "minecraft-datapack-language"
}
        
Elapsed time: 1.34054s