minecraft-datapack-language 15.4.28__py3-none-any.whl → 15.4.30__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. minecraft_datapack_language/__init__.py +23 -2
  2. minecraft_datapack_language/_version.py +2 -2
  3. minecraft_datapack_language/ast_nodes.py +87 -59
  4. minecraft_datapack_language/cli.py +276 -139
  5. minecraft_datapack_language/mdl_compiler.py +470 -0
  6. minecraft_datapack_language/mdl_errors.py +14 -0
  7. minecraft_datapack_language/mdl_lexer.py +624 -0
  8. minecraft_datapack_language/mdl_parser.py +573 -0
  9. minecraft_datapack_language-15.4.30.dist-info/METADATA +266 -0
  10. minecraft_datapack_language-15.4.30.dist-info/RECORD +17 -0
  11. minecraft_datapack_language/cli_build.py +0 -1292
  12. minecraft_datapack_language/cli_check.py +0 -155
  13. minecraft_datapack_language/cli_colors.py +0 -264
  14. minecraft_datapack_language/cli_help.py +0 -508
  15. minecraft_datapack_language/cli_new.py +0 -300
  16. minecraft_datapack_language/cli_utils.py +0 -276
  17. minecraft_datapack_language/expression_processor.py +0 -352
  18. minecraft_datapack_language/linter.py +0 -409
  19. minecraft_datapack_language/mdl_lexer_js.py +0 -754
  20. minecraft_datapack_language/mdl_parser_js.py +0 -1049
  21. minecraft_datapack_language/pack.py +0 -758
  22. minecraft_datapack_language-15.4.28.dist-info/METADATA +0 -1274
  23. minecraft_datapack_language-15.4.28.dist-info/RECORD +0 -25
  24. {minecraft_datapack_language-15.4.28.dist-info → minecraft_datapack_language-15.4.30.dist-info}/WHEEL +0 -0
  25. {minecraft_datapack_language-15.4.28.dist-info → minecraft_datapack_language-15.4.30.dist-info}/entry_points.txt +0 -0
  26. {minecraft_datapack_language-15.4.28.dist-info → minecraft_datapack_language-15.4.30.dist-info}/licenses/LICENSE +0 -0
  27. {minecraft_datapack_language-15.4.28.dist-info → minecraft_datapack_language-15.4.30.dist-info}/top_level.txt +0 -0
@@ -1,1274 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: minecraft-datapack-language
3
- Version: 15.4.28
4
- 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.
5
- Project-URL: Homepage, https://www.mcmdl.com
6
- Project-URL: Documentation, https://www.mcmdl.com/docs
7
- Project-URL: Repository, https://github.com/aaron777collins/MinecraftDatapackLanguage
8
- Project-URL: Bug Tracker, https://github.com/aaron777collins/MinecraftDatapackLanguage/issues
9
- Project-URL: VS Code Extension, https://marketplace.visualstudio.com/items?itemName=mdl.minecraft-datapack-language
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Operating System :: OS Independent
13
- Requires-Python: >=3.9
14
- Description-Content-Type: text/markdown
15
- License-File: LICENSE
16
- Requires-Dist: mecha>=0.99.0
17
- Provides-Extra: dev
18
- Requires-Dist: pytest>=7.0.0; extra == "dev"
19
- Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
20
- Dynamic: license-file
21
-
22
- # <img src="https://github.com/aaron777collins/MinecraftDatapackLanguage/raw/main/icons/icon-128.png" width="32" height="32" alt="MDL Icon"> Minecraft Datapack Language (MDL)
23
-
24
- A **modern JavaScript-style compiler** that lets you write Minecraft datapacks with **real control structures, variables, and expressions** that actually work.
25
-
26
- 📖 **[View Full Documentation](https://www.mcmdl.com/)** - Complete guides, examples, and API reference
27
- 📦 **[View on PyPI](https://pypi.org/project/minecraft-datapack-language/)** - Download and install from PyPI
28
- 🔧 **[VS Code Extension](https://marketplace.visualstudio.com/items?itemName=mdl.minecraft-datapack-language)** - Syntax highlighting, IntelliSense, and snippets
29
-
30
- ![CI](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/CI/badge.svg)
31
- ![Test Examples](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/Test%20Examples/badge.svg)
32
- ![Documentation](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/Build%20and%20Deploy%20Documentation/badge.svg)
33
- ![PyPI](https://img.shields.io/pypi/v/minecraft-datapack-language?style=flat-square)
34
- ![Release](https://github.com/aaron777collins/MinecraftDatapackLanguage/workflows/Release/badge.svg)
35
-
36
- ## 🎯 **MODERN** JavaScript-Style MDL Language
37
-
38
- **MDL uses a modern JavaScript-style language format** with **real control structures, variables, and expressions**:
39
-
40
- ### ✨ **MODERN** Features
41
- - **🎯 JavaScript-style syntax** with curly braces `{}` and semicolons `;`
42
- - **📝 Modern comments** using `//` and `/* */`
43
- - **🔢 Number variables** with `var num` type (stored in scoreboards)
44
- - **🔄 Full control structures** including `if/else if/else`, `while` loops with method selection
45
- - **💲 Variable substitution** with `$variable$` syntax
46
- - **🧮 Expressions** with arithmetic operations (`+`, `-`, `*`, `/`)
47
- - **📦 Namespace system** for modular code organization
48
- - **🎨 VS Code extension** with full IntelliSense and snippets
49
- - **🧪 Comprehensive testing** with E2E validation
50
- - **📚 Extensive documentation** with examples for every feature
51
-
52
- ### 🏗️ Core Features
53
- - ✅ **Modern pack format 82** by default for latest Minecraft features
54
- - ✅ **JavaScript-style syntax** with curly braces and semicolons
55
- - ✅ **Real control structures** - `if/else if/else`, `while` loops with recursion/schedule methods
56
- - ✅ **Number variables** stored in scoreboards with `$variable$` substitution
57
- - ✅ **Expressions** with arithmetic operations and variable substitution
58
- - ✅ **Multi-file projects** with automatic merging and dependency resolution
59
- - ✅ **Variable optimization** - automatic load function generation for initialization
60
- - ✅ **Selector optimization** - proper `@a` usage for system commands
61
- - ✅ **Easy hooks** into `minecraft:tick` and `minecraft:load` via function tags
62
- - ✅ **Tag support** for `function`, `item`, `block`, `entity_type`, `fluid`, and `game_event`
63
-
64
- > **Note**: Version 12.0+ uses **pack_format 82** by default for the modern JavaScript-style syntax.
65
-
66
- ---
67
-
68
- ## 🚀 Install
69
-
70
- ### Option A — from PyPI (recommended for users)
71
- Global, isolated CLI via **pipx**:
72
- ```bash
73
- python3 -m pip install --user pipx
74
- python3 -m pipx ensurepath # reopen terminal
75
- pipx install minecraft-datapack-language
76
-
77
- mdl --help
78
- ```
79
-
80
- Virtualenv (if you prefer):
81
- ```bash
82
- python3 -m venv .venv
83
- source .venv/bin/activate # Windows: .\.venv\Scripts\Activate.ps1
84
- pip install minecraft-datapack-language
85
- ```
86
-
87
- ### Option B — from source (for contributors)
88
- ```bash
89
- # inside the repo
90
- python -m pip install -e .
91
- ```
92
-
93
- ---
94
-
95
- ## 🔄 Update
96
-
97
- - **pipx**: `pipx upgrade minecraft-datapack-language`
98
- - **pip (venv)**: `pip install -U minecraft-datapack-language`
99
- - Pin a version: `pipx install "minecraft-datapack-language==<version>"` (replace `<version>` with desired version)
100
-
101
- ---
102
-
103
- ## 💻 CLI
104
-
105
- ### Modern JavaScript-style MDL (v15.0+)
106
- ```bash
107
- # Build JavaScript-style MDL files
108
- mdl build --mdl my_pack/mypack.mdl -o dist --wrapper mypack
109
- mdl check my_pack/mypack.mdl
110
-
111
- # Validate generated mcfunction files
112
- mdl check my_pack/mypack.mdl
113
-
114
- # Multi-file projects
115
- mdl build --mdl my_pack/ -o dist # Build entire directory
116
- mdl build --mdl "file1.mdl file2.mdl" -o dist # Build specific files
117
-
118
- # Create new projects
119
- mdl new my_awesome_pack
120
- ```
121
-
122
- ### 🐛 **Comprehensive Error Handling**
123
-
124
- MDL provides detailed error reporting with exact locations and helpful suggestions:
125
-
126
- ```bash
127
- # Check for errors with detailed output
128
- mdl check my_pack.mdl --verbose
129
- ```
130
-
131
- **Example Error Output:**
132
- ```
133
- Error 1: MDLSyntaxError in test.mdl:15:8
134
- Missing closing brace for if statement
135
- Context:
136
- 13: if (score > 10) {
137
- 14: say "High score!"
138
- 15: score = 0
139
- 16: }
140
-
141
- Suggestion: Add closing brace '}' after line 15
142
-
143
- Error 2: MDLLexerError in test.mdl:22:12
144
- Unterminated string literal
145
- Context:
146
- 20: say "Hello world
147
- 21: score = 10
148
- 22: say "Goodbye
149
-
150
- Suggestion: Add closing quote '"' at the end of line 20
151
- ```
152
-
153
- **Error Features:**
154
- - ✅ **Exact Location**: Line and column numbers for precise error location
155
- - ✅ **Context Lines**: Shows surrounding code for better debugging
156
- - ✅ **Helpful Suggestions**: Specific fix recommendations
157
- - ✅ **Multiple Error Collection**: Reports all errors, not just the first
158
- - ✅ **Error Types**: Syntax, Lexer, Parser, Validation, File, Build, and Configuration errors
159
-
160
- ### Comments in MDL
161
- MDL supports modern JavaScript-style comments:
162
- ```javascript
163
- // Single-line comments
164
- /* Multi-line comments */
165
-
166
- pack "My Pack" {
167
- function example() {
168
- // This comment will be properly converted to mcfunction
169
- say Hello World!;
170
- }
171
- }
172
- ```
173
-
174
- Generated mcfunction files will have proper `#` comments:
175
- ```mcfunction
176
- # This is a generated comment
177
- say Hello World!
178
- ```
179
-
180
- ### Build a whole folder of `.mdl` files
181
- ```bash
182
- mdl build --mdl src/ -o dist
183
- # Recursively parses src/**/*.mdl, merges into one pack (errors on duplicate functions).
184
- # Only the first file should have a pack declaration - all others are modules.
185
- ```
186
-
187
- ### Build multiple specific `.mdl` files
188
- ```bash
189
- mdl build --mdl "src/core.mdl src/features.mdl src/ui.mdl" -o dist
190
- # Parses multiple specific files and merges them into one datapack.
191
- # Only the first file should have a pack declaration - all others are modules.
192
- ```
193
-
194
- ### Validate a folder (JSON diagnostics)
195
- ```bash
196
- mdl check --json src/
197
- ```
198
-
199
- ---
200
-
201
- ## 📝 Quick Start - **MODERN** MDL
202
-
203
- Create your first modern MDL project:
204
-
205
- ```mdl
206
- // modern_pack.mdl
207
- pack "Modern Pack" description "A modern example" pack_format 82;
208
-
209
- namespace "example";
210
-
211
- // Number variables with expressions
212
- var num counter = 0;
213
- var num health = 20;
214
- var num level = 1;
215
- var num experience = 0;
216
-
217
- function "init" {
218
- say Initializing...;
219
- counter = 0;
220
- health = 20;
221
- level = 1;
222
- experience = 0;
223
- }
224
-
225
- function "tick" {
226
- counter = counter + 1;
227
-
228
- // Full if/else if/else control structure
229
- if "$health$ < 10" {
230
- say Health is low!;
231
- health = health + 5;
232
- effect give @a minecraft:regeneration 10 1;
233
- } else if "$level$ > 5" {
234
- say High level player!;
235
- effect give @a minecraft:strength 10 1;
236
- } else {
237
- say Normal player;
238
- effect give @a minecraft:speed 10 0;
239
- }
240
-
241
- // Variable substitution in strings
242
- say Counter: $counter$;
243
-
244
- // While loop with method selection
245
- while "$counter$ < 10" {
246
- counter = $counter$ + 1;
247
- say Counter: $counter$;
248
- }
249
-
250
- // Expressions with arithmetic
251
- experience = $level$ * 100 + $counter$;
252
- say Experience: $experience$;
253
- }
254
-
255
- // Lifecycle hooks
256
- on_load "example:init";
257
- on_tick "example:tick";
258
- ```
259
-
260
- Build and test:
261
- ```bash
262
- mdl build --mdl modern_pack.mdl -o dist
263
- # → dist/modern_pack/... and dist/modern_pack.zip
264
- ```
265
-
266
- ---
267
-
268
- ## 📁 Multi-file Support
269
-
270
- MDL supports building datapacks from multiple `.mdl` files. This is useful for organizing large projects into logical modules.
271
-
272
- ### How it works
273
- - **Directory scanning**: When you pass a directory to `--mdl`, MDL recursively finds all `.mdl` files
274
- - **File merging**: Each file is parsed into a `Pack` object, then merged into a single datapack
275
- - **Conflict resolution**: Duplicate function names within the same namespace will cause an error
276
- - **Pack metadata**: Only the **first file** should have a pack declaration (name, description, format)
277
- - **Module files**: Subsequent files should **not** have pack declarations - they are treated as modules
278
- - **Single file compilation**: When compiling a single file, it **must** have a pack declaration
279
-
280
- ### Best practices
281
- - **One pack declaration per project**: Only the **first file** should have a pack declaration
282
- - **Module files**: All other files should **not** have pack declarations - they are treated as modules
283
- - **Single file requirement**: When compiling a single file, it **must** have a pack declaration
284
- - **Organize by namespace**: Consider splitting files by namespace or feature
285
- - **Use descriptive filenames**: `core.mdl`, `combat.mdl`, `ui.mdl` etc.
286
- - **Avoid conflicts**: Ensure function names are unique within each namespace
287
-
288
- ### Example project structure
289
- ```
290
- my_datapack/
291
- ├── core.mdl # ✅ HAS pack declaration
292
- ├── combat/
293
- │ ├── weapons.mdl # ❌ NO pack declaration (module)
294
- │ └── armor.mdl # ❌ NO pack declaration (module)
295
- ├── ui/
296
- │ └── hud.mdl # ❌ NO pack declaration (module)
297
- └── data/
298
- └── recipes.mdl # ❌ NO pack declaration (module)
299
- ```
300
-
301
- **Important**: Only `core.mdl` should have a `pack "Name"` declaration. All other files are modules that merge into the main pack.
302
-
303
- ### Usage Examples
304
-
305
- **Build from directory:**
306
- ```bash
307
- mdl build --mdl my_datapack/ -o dist
308
- ```
309
-
310
- **Build from specific files:**
311
- ```bash
312
- mdl build --mdl "core.mdl combat.mdl ui.mdl" -o dist
313
- ```
314
-
315
- **Check entire project:**
316
- ```bash
317
- mdl check my_datapack/
318
- ```
319
-
320
- **Check with verbose output:**
321
- ```bash
322
- mdl build --mdl my_datapack/ -o dist --verbose
323
- ```
324
-
325
- ### Complete Multi-File Example
326
-
327
- Here's a complete example showing how to organize a datapack across multiple files:
328
-
329
- **`core.mdl`** (main file with pack declaration):
330
- ```mdl
331
- // core.mdl - Main pack and core systems
332
- pack "Adventure Pack" description "Multi-file example datapack" pack_format 82;
333
-
334
- namespace "core";
335
-
336
- // Number variables with expressions
337
- var num system_version = 1;
338
- var num player_count = 0;
339
- var num total_experience = 0;
340
-
341
- function "init" {
342
- say [core:init] Initializing Adventure Pack...;
343
- tellraw @a {"text":"Adventure Pack loaded!","color":"green"};
344
- system_version = 1;
345
- player_count = 0;
346
- total_experience = 0;
347
- }
348
-
349
- function "tick" {
350
- say [core:tick] Core systems running...;
351
- execute as @a run particle minecraft:end_rod ~ ~ ~ 0.1 0.1 0.1 0.01 1;
352
- player_count = player_count + 1;
353
-
354
- // Control structure example
355
- if "$player_count$ > 10" {
356
- say Many players online!;
357
- effect give @a minecraft:glowing 5 0;
358
- }
359
- }
360
-
361
- // Hook into vanilla lifecycle
362
- on_load "core:init";
363
- on_tick "core:tick";
364
- ```
365
-
366
- **`combat/weapons.mdl`** (combat module):
367
- ```mdl
368
- // combat/weapons.mdl - Weapon-related functions
369
- namespace "combat";
370
-
371
- var num weapon_damage = 10;
372
- var num critical_chance = 5;
373
-
374
- function "weapon_effects" {
375
- say [combat:weapon_effects] Applying weapon effects...;
376
- execute as @a[nbt={SelectedItem:{id:'minecraft:diamond_sword'}}] run effect give @s minecraft:strength 1 0 true;
377
- weapon_damage = weapon_damage + 2;
378
-
379
- // Expression example
380
- critical_chance = $weapon_damage$ / 2;
381
- }
382
-
383
- function "update_combat" {
384
- function core:tick;
385
- function combat:weapon_effects;
386
- }
387
- ```
388
-
389
- **`combat/armor.mdl`** (armor module):
390
- ```mdl
391
- // combat/armor.mdl - Armor-related functions
392
- namespace "combat";
393
-
394
- var num armor_bonus = 5;
395
- var num defense_rating = 0;
396
-
397
- function "armor_bonus" {
398
- say [combat:armor_bonus] Checking armor bonuses...;
399
- execute as @a[nbt={Inventory:[{Slot:103b,id:"minecraft:diamond_helmet"}]}] run effect give @s minecraft:resistance 1 0 true;
400
- armor_bonus = armor_bonus + 1;
401
-
402
- // Expression with multiple variables
403
- defense_rating = $armor_bonus$ * 2 + 10;
404
- }
405
-
406
- function "update_armor" {
407
- function combat:armor_bonus;
408
- }
409
- ```
410
-
411
- **`ui/hud.mdl`** (UI module):
412
- ```mdl
413
- // ui/hud.mdl - User interface functions
414
- namespace "ui";
415
-
416
- var num hud_version = 1;
417
- var num display_counter = 0;
418
-
419
- function "show_hud" {
420
- say [ui:show_hud] Updating HUD...;
421
- title @a actionbar {"text":"Adventure Pack Active","color":"gold"};
422
- hud_version = hud_version + 1;
423
-
424
- // While loop example
425
- while "$display_counter$ < 5" {
426
- display_counter = $display_counter$ + 1;
427
- say HUD update: $display_counter$;
428
- }
429
- }
430
-
431
- function "update_ui" {
432
- function ui:show_hud;
433
- function combat:update_combat;
434
- function combat:update_armor;
435
- }
436
- ```
437
-
438
- **Project structure:**
439
- ```
440
- adventure_pack/
441
- ├── core.mdl # ✅ HAS pack declaration
442
- ├── combat/
443
- │ ├── weapons.mdl # ❌ NO pack declaration (module)
444
- │ └── armor.mdl # ❌ NO pack declaration (module)
445
- └── ui/
446
- └── hud.mdl # ❌ NO pack declaration (module)
447
- ```
448
-
449
- **Build the project:**
450
- ```bash
451
- mdl build --mdl adventure_pack/ -o dist --verbose
452
- ```
453
-
454
- This will create a datapack with:
455
- - **Core systems** (initialization and tick functions)
456
- - **Combat features** (weapon and armor effects)
457
- - **UI elements** (HUD display)
458
- - **Cross-module calls** (UI calls combat functions)
459
- - **Variable optimization** (automatic load function generation)
460
-
461
- ### CLI Options for Multi-file Builds
462
-
463
- - `--mdl <path>`: Path to `.mdl` file, directory, or space-separated file list
464
- - `--src <path>`: Alias for `--mdl` (same functionality)
465
- - `-o, --out <dir>`: Output directory for the built datapack
466
- - `--wrapper <name>`: Custom wrapper folder/zip name (default: first namespace or pack name slug)
467
- - `--pack-format <N>`: Minecraft pack format (default: 82 for modern syntax)
468
- - `-v, --verbose`: Show detailed processing information including file merging
469
- - `--py-module <path>`: Alternative: build from Python module with `create_pack()` function
470
-
471
- ### Error Handling
472
-
473
- - **Missing pack declaration**: Single files must have a pack declaration
474
- - **Duplicate pack declarations**: Only the first file in a multi-file project should have a pack declaration
475
- - **Function conflicts**: Duplicate function names within the same namespace will cause an error
476
- - **Clear error messages**: Errors include file paths and line numbers for easy debugging
477
-
478
- ---
479
-
480
- ## 🎯 **Explicit Scope System**
481
-
482
- 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.
483
-
484
- ### **Variable Declaration Scopes**
485
-
486
- ```mdl
487
- // Player-specific variable (defaults to @s in execution context)
488
- var num playerScore = 0;
489
-
490
- // Server-wide variable (stored on server armor stand)
491
- var num globalCounter scope<global> = 0;
492
-
493
- // Team-specific variable
494
- var num teamScore scope<@a[team=red]> = 0;
495
-
496
- // Custom entity variable
497
- var num entityData scope<@e[type=armor_stand,tag=special,limit=1]> = 0;
498
- ```
499
-
500
- ### **Variable Access with Explicit Scopes**
501
-
502
- ```mdl
503
- // Each variable access must specify the scope
504
- playerScore<@s> = 42; // Player scope
505
- globalCounter<global> = 100; // Global scope
506
- teamScore<@a[team=red]> = 5; // Team scope
507
- entityData<@e[type=armor_stand,tag=special,limit=1]> = 10; // Custom entity
508
- ```
509
-
510
- ### **Explicit Scopes in Conditions**
511
-
512
- **NEW!** MDL now supports explicit scope selectors in if/while conditions, allowing you to override declared variable scopes:
513
-
514
- ```mdl
515
- function "check_scores" {
516
- // Check current player's score
517
- if "$playerScore<@s>$ > 10" {
518
- say "Your score is high!";
519
- }
520
-
521
- // Check global counter
522
- if "$globalCounter<global>$ > 100" {
523
- say "Global milestone reached!";
524
- }
525
-
526
- // Check another player's score
527
- if "$playerScore<@p[name=Steve]>$ > 20" {
528
- say "Steve has a good score!";
529
- }
530
-
531
- // Check team score
532
- if "$teamScore<@a[team=red]>$ > 50" {
533
- say "Red team is winning!";
534
- }
535
-
536
- // Use explicit scopes in while loops too
537
- while "$globalCounter<global>$ < 10" {
538
- globalCounter<global> = globalCounter<global> + 1;
539
- say "Counter: $globalCounter$";
540
- }
541
- }
542
- ```
543
-
544
- **Benefits:**
545
- - **Override declared scopes**: Use different scopes than what was declared
546
- - **Check other entities**: Compare scores across different players/teams
547
- - **Flexible conditions**: Mix and match scopes as needed
548
- - **Clear intent**: Explicit scope makes code more readable and debuggable
549
-
550
- ### **Scope Mapping**
551
-
552
- MDL maps scopes to Minecraft selectors:
553
-
554
- | MDL Scope | Minecraft Selector | Description |
555
- |-----------|-------------------|-------------|
556
- | `scope<global>` | `@e[type=armor_stand,tag=mdl_server,limit=1]` | Server-wide storage |
557
- | `scope<@s>` | `@s` | Current player |
558
- | `scope<@a>` | `@a` | All players |
559
- | `scope<@a[team=red]>` | `@a[team=red]` | Red team players |
560
- | `scope<@e[type=armor_stand,tag=something,limit=1]>` | `@e[type=armor_stand,tag=something,limit=1]` | Custom entity |
561
-
562
- ---
563
-
564
- ## 🎯 **Advanced Multi-File Examples with Namespaces**
565
-
566
- ### **Modern Namespace System**
567
-
568
- MDL's namespace system allows you to organize code across multiple files with proper separation:
569
-
570
- **`game.mdl`** - Core Game Logic:
571
- ```mdl
572
- pack "multi_game" "A multi-file game example" 82;
573
-
574
- namespace "game";
575
-
576
- var num player_score = 0;
577
- var num game_timer = 0;
578
- var num health = 20;
579
-
580
- function "main" {
581
- // If-else if-else chain
582
- if "$health$ < 10" {
583
- say "Health is low: $health$";
584
- health = $health$ + 5;
585
- } else if "$health$ > 15" {
586
- say "Health is good: $health$";
587
- } else {
588
- say "Health is moderate: $health$";
589
- }
590
-
591
- // While loop with counter
592
- while "$game_timer$ < 5" {
593
- game_timer = $game_timer$ + 1;
594
- say "Game Timer: $game_timer$";
595
- }
596
- }
597
-
598
- function "score_update" {
599
- player_score = $player_score$ + 10;
600
- say "Score updated: $player_score$";
601
- }
602
-
603
- on_tick "game:main";
604
- ```
605
-
606
- **`ui.mdl`** - User Interface:
607
- ```mdl
608
- namespace "ui";
609
-
610
- var num menu_state = 0;
611
- var num selected_option = 1;
612
-
613
- function "main" {
614
- // Show menu based on state
615
- if "$menu_state$ == 0" {
616
- say "=== Main Menu ===";
617
- say "1. Start Game";
618
- say "2. Options";
619
- say "3. Exit";
620
- }
621
-
622
- // Handle selection
623
- if "$selected_option$ == 1" {
624
- say "Starting game...";
625
- } else if "$selected_option$ == 2" {
626
- say "Opening options...";
627
- } else if "$selected_option$ == 3" {
628
- say "Exiting...";
629
- }
630
- }
631
-
632
- function "button_handler" {
633
- var num button_id = 0;
634
-
635
- if "$button_id$ == 1" {
636
- selected_option = 1;
637
- say "Option 1 selected";
638
- } else if "$button_id$ == 2" {
639
- selected_option = 2;
640
- say "Option 2 selected";
641
- }
642
- }
643
-
644
- on_load "ui:main";
645
- ```
646
-
647
- **`combat.mdl`** - Combat System:
648
- ```mdl
649
- namespace "combat";
650
-
651
- var num enemy_count = 5;
652
- var num damage = 0;
653
-
654
- function "main" {
655
- var num total_damage = 0;
656
- total_damage = $damage$ * 2;
657
-
658
- if "$total_damage$ > 20" {
659
- say "Critical hit! Damage: $total_damage$";
660
- } else {
661
- say "Normal hit. Damage: $total_damage$";
662
- }
663
-
664
- // Variable substitution in tellraw
665
- tellraw @a [{"text":"Enemy Count: "},{"score":{"name":"@a","objective":"enemy_count"}}];
666
- }
667
-
668
- on_tick "combat:main";
669
- ```
670
-
671
- ### **Build and Generated Structure**
672
-
673
- ```bash
674
- # Build all files together
675
- mdl build --mdl . -o dist
676
-
677
- # Or build specific files
678
- mdl build --mdl "game.mdl ui.mdl combat.mdl" -o dist
679
- ```
680
-
681
- **Generated Structure:**
682
- ```
683
- dist/
684
- ├── data/
685
- │ ├── minecraft/tags/function/
686
- │ │ ├── load.json # Contains all load functions
687
- │ │ └── tick.json # Contains all tick functions
688
- │ ├── game/ # game.mdl namespace
689
- │ │ └── function/
690
- │ │ ├── main.mcfunction
691
- │ │ └── score_update.mcfunction
692
- │ ├── ui/ # ui.mdl namespace
693
- │ │ └── function/
694
- │ │ ├── main.mcfunction
695
- │ │ └── button_handler.mcfunction
696
- │ └── combat/ # combat.mdl namespace
697
- │ └── function/
698
- │ └── main.mcfunction
699
- └── pack.mcmeta
700
- ```
701
-
702
- ### **Key Benefits of Namespace System**
703
-
704
- - ✅ **No function name conflicts** - Each namespace is completely separate
705
- - ✅ **Modular development** - Work on different features in separate files
706
- - ✅ **Automatic merging** - All variables and functions are combined intelligently
707
- - ✅ **Proper initialization** - Variables are automatically set up in load functions
708
- - ✅ **Clean organization** - Each module has its own directory structure
709
- - ✅ **Easy maintenance** - Update individual modules without affecting others
710
-
711
- ### **Complete Example Project**
712
-
713
- Check out the `examples/multi_file_example/` directory for a complete working example with:
714
- - Multiple namespaces (`test`, `other`, `ui`)
715
- - Various control structures and expressions
716
- - Comprehensive documentation
717
- - Ready-to-build files
718
-
719
- ---
720
-
721
- ## 📝 The **MODERN** `.mdl` Language
722
-
723
- ### Grammar you can rely on (based on the parser)
724
- - **pack header** (required once):
725
- ```mdl
726
- pack "Name" [description "Desc"] [pack_format N];
727
- ```
728
- - **namespace** (selects a namespace for following blocks):
729
- ```mdl
730
- namespace "example";
731
- ```
732
- - **number variable declarations** (only `num` type supported):
733
- ```mdl
734
- var num counter = 0;
735
- var num health = 20;
736
- var num level = 1;
737
- ```
738
- - **function** (curly braces + semicolons):
739
- ```mdl
740
- function "hello" {
741
- say hi;
742
- tellraw @a {"text":"ok","color":"green"};
743
- }
744
- ```
745
- - **full conditional blocks** (if/else if/else statements):
746
- ```mdl
747
- function "conditional" {
748
- if "$health$ < 10" {
749
- say Health is low!;
750
- effect give @s minecraft:glowing 5 1;
751
- } else if "$level$ > 5" {
752
- say High level player!;
753
- effect give @s minecraft:speed 5 1;
754
- } else {
755
- say Normal player;
756
- effect give @s minecraft:jump_boost 5 0;
757
- }
758
- }
759
- ```
760
- - **while loops** (repetitive execution with method selection):
761
- ```mdl
762
- function "countdown" {
763
- var num counter = 5;
764
- while "$counter$ > 0" {
765
- say Counter: $counter$;
766
- counter = counter - 1;
767
- }
768
-
769
- // Schedule method for performance
770
- counter = 10;
771
- while "$counter$ > 0" method="schedule" {
772
- say Schedule counter: $counter$;
773
- counter = $counter$ - 1;
774
- }
775
- }
776
- ```
777
- - **expressions** (arithmetic operations):
778
- ```mdl
779
- function "expressions" {
780
- var num a = 10;
781
- var num b = 5;
782
- var num result = $a$ + $b$ * 2;
783
- say Result: $result$;
784
- }
785
- ```
786
- - **function calls** (one function invoking another with fully qualified ID):
787
- ```mdl
788
- function "outer" {
789
- say I will call another function;
790
- function example:hello;
791
- }
792
- ```
793
- - **hooks** (namespaced ids required):
794
- ```mdl
795
- on_load "example:hello";
796
- on_tick "example:hello";
797
- ```
798
- - **tags** (supported registries: `function`, `item`, `block`, `entity_type`, `fluid`, `game_event`):
799
- ```mdl
800
- tag function "minecraft:tick" {
801
- add "example:hello";
802
- }
803
- ```
804
- - **comments** start with `//` or `/* */`. Hashes inside **quoted strings** are preserved.
805
- - **whitespace**: empty lines are ignored; **explicit block boundaries** using curly braces `{` and `}`; **statement termination** using semicolons `;`.
806
-
807
- > 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.
808
-
809
- ### Comments
810
-
811
- MDL supports modern JavaScript-style comments:
812
-
813
- - **Full-line comments** (a line starting with `//`) are ignored by the parser.
814
- - **Block comments** (`/* */`) are supported for multi-line comments.
815
- - **Inline `#` characters** are preserved inside function bodies, so you can still use them the way `mcfunction` normally allows.
816
-
817
- Example:
818
-
819
- ```mdl
820
- // Comment Demo - Testing comments
821
- pack "Comment Demo" description "Testing comments";
822
-
823
- namespace "demo";
824
-
825
- function "comments" {
826
- // This whole line is ignored by MDL
827
- say Hello; // This inline comment is preserved
828
- tellraw @a {"text":"World","color":"blue"}; // Inline too!
829
-
830
- /* This is a block comment
831
- that spans multiple lines
832
- and is ignored by the parser */
833
- }
834
- ```
835
-
836
- When compiled, the resulting function looks like:
837
-
838
- ```mcfunction
839
- say Hello # This inline comment is preserved
840
- tellraw @a {"text":"World","color":"blue"} # Inline too!
841
- ```
842
-
843
- Notice how the full-line `//` and block comments never make it into the `.mcfunction`, but the inline ones do.
844
-
845
- ---
846
-
847
- ### **MODERN** Variables and Data Types
848
-
849
- MDL supports **number variables** with **expressions and arithmetic operations**:
850
-
851
- #### Number Variables (`num`)
852
- ```mdl
853
- var num counter = 0;
854
- var num health = 20;
855
- var num experience = 100;
856
-
857
- // Arithmetic operations
858
- counter = counter + 1;
859
- health = health - 5;
860
- experience = experience * 2;
861
-
862
- // Expressions with multiple variables
863
- var num total = $health$ + $experience$;
864
- var num average = $total$ / 2;
865
-
866
- // Variable substitution in strings
867
- say Health: $health$;
868
- say Experience: $experience$;
869
- say Total: $total$;
870
- ```
871
-
872
- **Variable Substitution**: Use `$variable_name$` to read values from scoreboards in strings and conditions.
873
-
874
- **Expressions**: Support for arithmetic operations (`+`, `-`, `*`, `/`) with proper order of operations.
875
-
876
- ### **MODERN** Control Flow
877
-
878
- MDL supports full conditional blocks and loops for control flow.
879
-
880
- #### Conditional Blocks
881
-
882
- MDL supports complete if/else if/else statements for conditional execution:
883
-
884
- ```mdl
885
- function "conditional_example" {
886
- var num player_level = 15;
887
- var num player_health = 8;
888
- var num player_experience = 1000;
889
-
890
- if "$player_level$ >= 10" {
891
- if "$player_health$ < 10" {
892
- say Advanced player with low health!;
893
- effect give @s minecraft:regeneration 10 1;
894
- player_health = $player_health$ + 10;
895
- } else {
896
- say Advanced player with good health;
897
- effect give @s minecraft:strength 10 1;
898
- }
899
- } else if "$player_level$ >= 5" {
900
- say Intermediate player;
901
- effect give @s minecraft:speed 10 0;
902
- } else {
903
- say Beginner player;
904
- effect give @s minecraft:jump_boost 10 0;
905
- }
906
-
907
- // Expression in condition
908
- if "$player_experience$ > $player_level$ * 100" {
909
- say High experience for level!;
910
- }
911
- }
912
- ```
913
-
914
- **Rules:**
915
- - Conditions use `$variable$` syntax for variable substitution
916
- - **Explicit block boundaries**: Conditional blocks use curly braces `{` and `}`
917
- - **Statement termination**: All commands must end with semicolons `;`
918
- - You can have multiple `else if` blocks
919
- - The `else` block is optional
920
- - Conditional blocks are compiled to separate functions and called with `execute` commands
921
- - **Proper logic**: `else if` blocks only execute if previous conditions were false
922
- - **Expressions in conditions**: Support for arithmetic operations in conditions
923
-
924
- #### While Loops
925
-
926
- MDL supports while loops with method selection for repetitive execution:
927
-
928
- ```mdl
929
- function "while_example" {
930
- var num counter = 5;
931
-
932
- // Default recursion method (immediate execution)
933
- while "$counter$ > 0" {
934
- say "Counter: $counter$";
935
- counter = $counter$ - 1;
936
- }
937
-
938
- // Schedule method (spreads across ticks for performance)
939
- counter = 10;
940
- while "$counter$ > 0" method="schedule" {
941
- say "Schedule counter: $counter$";
942
- counter = $counter$ - 1;
943
- }
944
-
945
- // Expression in loop condition
946
- var num max_count = 5;
947
- counter = 0;
948
- while "$counter$ < $max_count$ * 2" {
949
- say "Expression counter: $counter$";
950
- counter = $counter$ + 1;
951
- }
952
- }
953
- ```
954
-
955
- **Rules:**
956
- - Conditions use `$variable$` syntax for variable substitution
957
- - **Explicit block boundaries**: While loops use curly braces `{` and `}`
958
- - **Statement termination**: All commands must end with semicolons `;`
959
- - While loops continue until the condition becomes false
960
- - **Method Selection**: Choose `method="recursion"` (default) or `method="schedule"`
961
- - **Recursion method**: Executes all iterations immediately (good for small loops)
962
- - **Schedule method**: Spreads iterations across ticks (better for long loops, prevents lag)
963
- - **Important**: Ensure your loop body modifies the condition to avoid infinite loops
964
- - **Expressions in conditions**: Support for arithmetic operations in loop conditions
965
-
966
- **Implementation**: While loops generate separate function files with proper recursive calls to continue execution until the condition becomes false.
967
-
968
- ---
969
-
970
- ### Multi-line Commands
971
-
972
- Long JSON commands can be split across multiple lines with a trailing backslash `\`.
973
- MDL will join them back together before writing the final `.mcfunction`.
974
-
975
- Example:
976
-
977
- ```mdl
978
- // Multi-line Demo
979
- pack "Multi-line Demo";
980
-
981
- namespace "demo";
982
-
983
- function "multiline" {
984
- tellraw @a \
985
- {"text":"This text is really, really long so we split it",\
986
- "color":"gold"};
987
- }
988
- ```
989
-
990
- When compiled, the function is a single line:
991
-
992
- ```mcfunction
993
- tellraw @a {"text":"This text is really, really long so we split it","color":"gold"}
994
- ```
995
-
996
- ---
997
-
998
- ## 🎯 **MODERN** example (control structures + variables + expressions)
999
-
1000
- ```mdl
1001
- // modern_pack.mdl - modern example for Minecraft Datapack Language
1002
- pack "Modern Pack" description "Modern example datapack" pack_format 82;
1003
-
1004
- namespace "example";
1005
-
1006
- // Number variables with expressions
1007
- var num counter = 0;
1008
- var num health = 20;
1009
- var num level = 1;
1010
- var num experience = 0;
1011
-
1012
- function "inner" {
1013
- say [example:inner] This is the inner function;
1014
- tellraw @a {"text":"Running inner","color":"yellow"};
1015
- counter = counter + 1;
1016
- }
1017
-
1018
- function "hello" {
1019
- say [example:hello] Outer says hi;
1020
- function example:inner;
1021
- tellraw @a {"text":"Back in hello","color":"aqua"};
1022
-
1023
- // Variable operations with expressions
1024
- health = health + 5;
1025
- level = level + 1;
1026
- experience = $level$ * 100 + $counter$;
1027
-
1028
- // Variable substitution
1029
- say Health: $health$;
1030
- say Level: $level$;
1031
- say Experience: $experience$;
1032
-
1033
- // Full control structures
1034
- if "$health$ > 15" {
1035
- say High health!;
1036
- effect give @s minecraft:strength 10 1;
1037
- } else if "$level$ > 5" {
1038
- say High level!;
1039
- effect give @s minecraft:speed 10 1;
1040
- } else {
1041
- say Normal stats;
1042
- effect give @s minecraft:jump_boost 10 0;
1043
- }
1044
-
1045
- // While loop with method selection
1046
- while "$counter$ < 5" {
1047
- say Counter: $counter$;
1048
- counter = counter + 1;
1049
- }
1050
-
1051
- // Expression in condition
1052
- if "$experience$ > $level$ * 50" {
1053
- say High experience for level!;
1054
- }
1055
- }
1056
-
1057
- // Hook the function into load and tick
1058
- on_load "example:hello";
1059
- on_tick "example:hello";
1060
-
1061
- // Second namespace with a cross-namespace call
1062
- namespace "util";
1063
-
1064
- var num helper_count = 0;
1065
- var num total_help = 0;
1066
-
1067
- function "helper" {
1068
- say [util:helper] Helping out...;
1069
- helper_count = helper_count + 1;
1070
- total_help = $helper_count$ * 10;
1071
- say Helper count: $helper_count$;
1072
- say Total help: $total_help$;
1073
- }
1074
-
1075
- function "boss" {
1076
- say [util:boss] Calling example:hello then util:helper;
1077
- function example:hello;
1078
- function util:helper;
1079
- }
1080
-
1081
- // Run boss every tick as well
1082
- on_tick "util:boss";
1083
-
1084
- // Function tag examples
1085
- tag function "minecraft:load" {
1086
- add "example:hello";
1087
- }
1088
-
1089
- tag function "minecraft:tick" {
1090
- add "example:hello";
1091
- add "util:boss";
1092
- }
1093
-
1094
- // Data tag examples across registries
1095
- tag item "example:swords" {
1096
- add "minecraft:diamond_sword";
1097
- add "minecraft:netherite_sword";
1098
- }
1099
-
1100
- tag block "example:glassy" {
1101
- add "minecraft:glass";
1102
- add "minecraft:tinted_glass";
1103
- }
1104
- ```
1105
-
1106
- ### What this demonstrates
1107
- - **Nested-like function composition** (`function example:inner` inside `function "hello"`).
1108
- - **Multiple namespaces** (`example`, `util`) calling each other with fully-qualified IDs.
1109
- - **Lifecycle hooks** (`on_load`, `on_tick`) on both `example:hello` and `util:boss`.
1110
- - **Function tags** to participate in vanilla tags (`minecraft:load`, `minecraft:tick`).
1111
- - **Data tags** (`item`, `block`) in addition to function tags.
1112
- - **Number variables** with `$variable$` substitution.
1113
- - **Expressions** with arithmetic operations and variable substitution.
1114
- - **Full control structures** - `if/else if/else`, `while` loops with method selection.
1115
- - **Modern syntax** with curly braces and semicolons.
1116
- - **Variable optimization** - automatic load function generation.
1117
-
1118
- ---
1119
-
1120
- ## 🐍 Python API equivalent
1121
-
1122
- ```python
1123
- from minecraft_datapack_language import Pack
1124
-
1125
- def build_pack():
1126
- p = Pack(name="Modern Pack",
1127
- description="Modern example datapack",
1128
- pack_format=82)
1129
-
1130
- ex = p.namespace("example")
1131
- ex.function("inner",
1132
- 'say [example:inner] This is the inner function',
1133
- 'tellraw @a {"text":"Running inner","color":"yellow"}'
1134
- )
1135
- ex.function("hello",
1136
- 'say [example:hello] Outer says hi',
1137
- 'function example:inner',
1138
- 'tellraw @a {"text":"Back in hello","color":"aqua"}'
1139
- )
1140
-
1141
- # Hooks for example namespace
1142
- p.on_load("example:hello")
1143
- p.on_tick("example:hello")
1144
-
1145
- util = p.namespace("util")
1146
- util.function("helper",
1147
- 'say [util:helper] Helping out...'
1148
- )
1149
- util.function("boss",
1150
- 'say [util:boss] Calling example:hello then util:helper',
1151
- 'function example:hello',
1152
- 'function util:helper'
1153
- )
1154
-
1155
- # Tick hook for util namespace
1156
- p.on_tick("util:boss")
1157
-
1158
- # Function tags
1159
- p.tag("function", "minecraft:load", values=["example:hello"])
1160
- p.tag("function", "minecraft:tick", values=["example:hello", "util:boss"])
1161
-
1162
- # Data tags
1163
- p.tag("item", "example:swords", values=["minecraft:diamond_sword", "minecraft:netherite_sword"])
1164
- p.tag("block", "example:glassy", values=["minecraft:glass", "minecraft:tinted_glass"])
1165
-
1166
- return p
1167
- ```
1168
-
1169
- Build it:
1170
- ```bash
1171
- python - <<'PY'
1172
- from my_pack_module import build_pack
1173
- from minecraft_datapack_language.cli import main as M
1174
- # write to dist/ with a wrapper folder name 'mypack'
1175
- p = build_pack()
1176
- M(['build', '--py-object', 'my_pack_module:build_pack', '-o', 'dist', '--wrapper', 'mypack', '--pack-format', '82'])
1177
- PY
1178
- ```
1179
-
1180
- ---
1181
-
1182
- ## 🔧 Development System
1183
-
1184
- MDL includes a comprehensive development system that allows you to work with both stable and development versions simultaneously.
1185
-
1186
- ### Quick Setup
1187
-
1188
- **Linux/macOS:**
1189
- ```bash
1190
- ./scripts/dev_setup.sh
1191
- ```
1192
-
1193
- **Windows (PowerShell):**
1194
- ```powershell
1195
- .\scripts\dev_setup.ps1
1196
- ```
1197
-
1198
- ### Development Commands
1199
-
1200
- - **`mdl`** - Stable, globally installed version
1201
- - **`mdlbeta`** - Local development version for testing changes
1202
-
1203
- ### Development Workflow
1204
-
1205
- 1. **Make changes** to the code
1206
- 2. **Rebuild** the development version:
1207
- ```bash
1208
- ./scripts/dev_build.sh
1209
- ```
1210
- 3. **Test** your changes with `mdlbeta`:
1211
- ```bash
1212
- mdlbeta build --mdl your_file.mdl -o dist
1213
- ```
1214
- 4. **Compare** with stable version:
1215
- ```bash
1216
- mdl build --mdl your_file.mdl -o dist_stable
1217
- ```
1218
-
1219
- ### Testing
1220
-
1221
- **Test the development environment:**
1222
- ```bash
1223
- # Linux/macOS
1224
- ./scripts/test_dev.sh
1225
-
1226
- # Windows (PowerShell)
1227
- .\scripts\test_dev.ps1
1228
- ```
1229
-
1230
- For more details, see [DEVELOPMENT.md](DEVELOPMENT.md).
1231
-
1232
- ## 🔧 VS Code Extension
1233
-
1234
- Get syntax highlighting, error checking, and build commands for `.mdl` files in VS Code, Cursor, and other VS Code-based editors.
1235
-
1236
- ### Quick Install
1237
-
1238
- 1. **Download from [GitHub Releases](https://github.com/aaron777collins/MinecraftDatapackLanguage/releases)**
1239
- 2. **Install the `.vsix` file**:
1240
- - Open VS Code/Cursor
1241
- - Go to Extensions (Ctrl+Shift+X)
1242
- - Click "..." → "Install from VSIX..."
1243
- - Choose the downloaded `.vsix` file
1244
-
1245
- ### Features
1246
- - **Syntax highlighting** for `.mdl` files
1247
- - **Real-time error checking** with error detection
1248
- - **Build commands**: `MDL: Build current file` and `MDL: Check Workspace`
1249
- - **Workspace validation** for multi-file projects
1250
- - **Server function support**: Proper `@a` selector usage for tag-called functions
1251
-
1252
- ### Development Setup
1253
- ```bash
1254
- cd vscode-extension/
1255
- npm i
1256
- # Press F5 to launch the Extension Dev Host
1257
- ```
1258
-
1259
- ---
1260
-
1261
- ## 🚀 CI & Releases
1262
-
1263
- - **CI** runs on push/PR across Linux/macOS/Windows and uploads artifacts.
1264
- - **Release** is triggered by pushing a tag like `v1.0.0` or via the Release workflow manually.
1265
- - Versions are derived from git tags via **setuptools-scm**; tag `vX.Y.Z` → package version `X.Y.Z`.
1266
-
1267
- ### Local release helper
1268
- ```bash
1269
- # requires GitHub CLI: gh auth login
1270
- ./scripts/release.sh patch "Fixes"
1271
- ./scripts/release.sh minor "Features"
1272
- ./scripts/release.sh major "Breaking"
1273
- ./scripts/release.sh v1.2.3 "Exact version"
1274
- ```