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.
- minecraft_datapack_language/__init__.py +23 -2
- minecraft_datapack_language/_version.py +2 -2
- minecraft_datapack_language/ast_nodes.py +87 -59
- minecraft_datapack_language/cli.py +276 -139
- minecraft_datapack_language/mdl_compiler.py +470 -0
- minecraft_datapack_language/mdl_errors.py +14 -0
- minecraft_datapack_language/mdl_lexer.py +624 -0
- minecraft_datapack_language/mdl_parser.py +573 -0
- minecraft_datapack_language-15.4.30.dist-info/METADATA +266 -0
- minecraft_datapack_language-15.4.30.dist-info/RECORD +17 -0
- minecraft_datapack_language/cli_build.py +0 -1292
- minecraft_datapack_language/cli_check.py +0 -155
- minecraft_datapack_language/cli_colors.py +0 -264
- minecraft_datapack_language/cli_help.py +0 -508
- minecraft_datapack_language/cli_new.py +0 -300
- minecraft_datapack_language/cli_utils.py +0 -276
- minecraft_datapack_language/expression_processor.py +0 -352
- minecraft_datapack_language/linter.py +0 -409
- minecraft_datapack_language/mdl_lexer_js.py +0 -754
- minecraft_datapack_language/mdl_parser_js.py +0 -1049
- minecraft_datapack_language/pack.py +0 -758
- minecraft_datapack_language-15.4.28.dist-info/METADATA +0 -1274
- minecraft_datapack_language-15.4.28.dist-info/RECORD +0 -25
- {minecraft_datapack_language-15.4.28.dist-info → minecraft_datapack_language-15.4.30.dist-info}/WHEEL +0 -0
- {minecraft_datapack_language-15.4.28.dist-info → minecraft_datapack_language-15.4.30.dist-info}/entry_points.txt +0 -0
- {minecraft_datapack_language-15.4.28.dist-info → minecraft_datapack_language-15.4.30.dist-info}/licenses/LICENSE +0 -0
- {minecraft_datapack_language-15.4.28.dist-info → minecraft_datapack_language-15.4.30.dist-info}/top_level.txt +0 -0
@@ -1,159 +1,296 @@
|
|
1
|
+
#!/usr/bin/env python3
|
1
2
|
"""
|
2
|
-
MDL CLI -
|
3
|
-
Handles basic control structures and number variables only
|
3
|
+
MDL CLI - Command Line Interface for Minecraft Datapack Language
|
4
4
|
"""
|
5
5
|
|
6
6
|
import argparse
|
7
7
|
import sys
|
8
|
+
import os
|
8
9
|
from pathlib import Path
|
9
|
-
from
|
10
|
-
|
11
|
-
from .
|
12
|
-
from .
|
13
|
-
from .cli_new import create_new_project
|
14
|
-
from .cli_help import show_main_help, show_build_help, show_check_help, show_new_help
|
15
|
-
from .mdl_errors import MDLErrorCollector, create_error, MDLConfigurationError
|
10
|
+
from .mdl_lexer import MDLLexer
|
11
|
+
from .mdl_parser import MDLParser
|
12
|
+
from .mdl_compiler import MDLCompiler
|
13
|
+
from .mdl_errors import MDLLexerError, MDLParserError, MDLCompilerError
|
16
14
|
|
17
15
|
|
18
16
|
def main():
|
19
17
|
"""Main CLI entry point."""
|
20
|
-
|
18
|
+
parser = argparse.ArgumentParser(
|
19
|
+
description="MDL (Minecraft Datapack Language) - Compile MDL files to Minecraft datapacks",
|
20
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
21
|
+
epilog="""
|
22
|
+
Examples:
|
23
|
+
mdl build --mdl main.mdl -o dist # Build a single MDL file
|
24
|
+
mdl build --mdl . -o dist # Build all MDL files in current directory
|
25
|
+
mdl check main.mdl # Check syntax without building
|
26
|
+
mdl new my_project # Create a new project
|
27
|
+
"""
|
28
|
+
)
|
29
|
+
|
30
|
+
subparsers = parser.add_subparsers(dest='command', help='Available commands')
|
31
|
+
|
32
|
+
# Build command
|
33
|
+
build_parser = subparsers.add_parser('build', help='Build MDL files into a datapack')
|
34
|
+
build_parser.add_argument('--mdl', required=True, help='MDL file(s) or directory to build')
|
35
|
+
build_parser.add_argument('-o', '--output', required=True, help='Output directory for the datapack')
|
36
|
+
build_parser.add_argument('--verbose', action='store_true', help='Show detailed output')
|
37
|
+
|
38
|
+
# Check command
|
39
|
+
check_parser = subparsers.add_parser('check', help='Check MDL files for syntax errors')
|
40
|
+
check_parser.add_argument('files', nargs='+', help='MDL files to check')
|
41
|
+
check_parser.add_argument('--verbose', action='store_true', help='Show detailed output')
|
42
|
+
|
43
|
+
# New command
|
44
|
+
new_parser = subparsers.add_parser('new', help='Create a new MDL project')
|
45
|
+
new_parser.add_argument('project_name', help='Name of the new project')
|
46
|
+
new_parser.add_argument('--pack-name', help='Custom name for the datapack')
|
47
|
+
new_parser.add_argument('--pack-format', type=int, default=82, help='Pack format number (default: 82)')
|
48
|
+
|
49
|
+
args = parser.parse_args()
|
50
|
+
|
51
|
+
if not args.command:
|
52
|
+
parser.print_help()
|
53
|
+
return 1
|
21
54
|
|
22
55
|
try:
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
)
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
check_parser.add_argument('input', help='Input MDL file or directory')
|
70
|
-
check_parser.add_argument('--verbose', '-v', action='store_true', help='Verbose output')
|
71
|
-
check_parser.add_argument('--ignore-warnings', action='store_true', help='Suppress warning messages during check')
|
72
|
-
|
73
|
-
# New command
|
74
|
-
new_parser = subparsers.add_parser('new', add_help=False)
|
75
|
-
new_parser.add_argument('project_name', help='Name for the new project')
|
76
|
-
new_parser.add_argument('--pack-name', help='Custom pack name')
|
77
|
-
new_parser.add_argument('--pack-format', type=int, default=82, help='Pack format number')
|
78
|
-
|
56
|
+
if args.command == 'build':
|
57
|
+
return build_command(args)
|
58
|
+
elif args.command == 'check':
|
59
|
+
return check_command(args)
|
60
|
+
elif args.command == 'new':
|
61
|
+
return new_command(args)
|
62
|
+
else:
|
63
|
+
print(f"Unknown command: {args.command}")
|
64
|
+
return 1
|
65
|
+
except Exception as e:
|
66
|
+
print(f"Error: {e}")
|
67
|
+
if args.verbose:
|
68
|
+
import traceback
|
69
|
+
traceback.print_exc()
|
70
|
+
return 1
|
71
|
+
|
72
|
+
|
73
|
+
def build_command(args):
|
74
|
+
"""Build MDL files into a datapack."""
|
75
|
+
mdl_path = Path(args.mdl)
|
76
|
+
output_dir = Path(args.output)
|
77
|
+
|
78
|
+
if not mdl_path.exists():
|
79
|
+
print(f"Error: MDL path '{mdl_path}' does not exist")
|
80
|
+
return 1
|
81
|
+
|
82
|
+
# Determine what to build
|
83
|
+
if mdl_path.is_file():
|
84
|
+
mdl_files = [mdl_path]
|
85
|
+
elif mdl_path.is_dir():
|
86
|
+
mdl_files = list(mdl_path.glob("**/*.mdl"))
|
87
|
+
if not mdl_files:
|
88
|
+
print(f"Error: No .mdl files found in directory '{mdl_path}'")
|
89
|
+
return 1
|
90
|
+
else:
|
91
|
+
print(f"Error: Invalid MDL path '{mdl_path}'")
|
92
|
+
return 1
|
93
|
+
|
94
|
+
if args.verbose:
|
95
|
+
print(f"Building {len(mdl_files)} MDL file(s)...")
|
96
|
+
for f in mdl_files:
|
97
|
+
print(f" {f}")
|
98
|
+
|
99
|
+
# Parse and compile each file
|
100
|
+
all_asts = []
|
101
|
+
for mdl_file in mdl_files:
|
79
102
|
try:
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
+
with open(mdl_file, 'r', encoding='utf-8') as f:
|
104
|
+
source = f.read()
|
105
|
+
|
106
|
+
if args.verbose:
|
107
|
+
print(f"Parsing {mdl_file}...")
|
108
|
+
|
109
|
+
parser = MDLParser(str(mdl_file))
|
110
|
+
ast = parser.parse(source)
|
111
|
+
all_asts.append(ast)
|
112
|
+
|
113
|
+
except (MDLLexerError, MDLParserError) as e:
|
114
|
+
print(f"Error in {mdl_file}: {e}")
|
115
|
+
return 1
|
116
|
+
|
117
|
+
# Merge all ASTs if multiple files
|
118
|
+
if len(all_asts) == 1:
|
119
|
+
final_ast = all_asts[0]
|
120
|
+
else:
|
121
|
+
# Merge multiple ASTs
|
122
|
+
final_ast = all_asts[0]
|
123
|
+
for ast in all_asts[1:]:
|
124
|
+
final_ast.variables.extend(ast.variables)
|
125
|
+
final_ast.functions.extend(ast.functions)
|
126
|
+
final_ast.tags.extend(ast.tags)
|
127
|
+
final_ast.hooks.extend(ast.hooks)
|
128
|
+
final_ast.statements.extend(ast.statements)
|
129
|
+
|
130
|
+
# Compile
|
131
|
+
try:
|
132
|
+
if args.verbose:
|
133
|
+
print(f"Compiling to {output_dir}...")
|
103
134
|
|
104
|
-
|
105
|
-
|
106
|
-
input_path = Path(args.input)
|
107
|
-
if input_path.is_file():
|
108
|
-
lint_mdl_file_wrapper(args.input, args.verbose, args.ignore_warnings)
|
109
|
-
else:
|
110
|
-
lint_mdl_directory_wrapper(args.input, args.verbose, args.ignore_warnings)
|
111
|
-
except Exception as e:
|
112
|
-
error_collector.add_error(create_error(
|
113
|
-
MDLConfigurationError,
|
114
|
-
f"Check command failed: {str(e)}",
|
115
|
-
suggestion="Check your arguments and try again."
|
116
|
-
))
|
135
|
+
compiler = MDLCompiler()
|
136
|
+
output_path = compiler.compile(final_ast, str(output_dir))
|
117
137
|
|
118
|
-
|
119
|
-
|
120
|
-
create_new_project(
|
121
|
-
args.project_name,
|
122
|
-
pack_name=args.pack_name,
|
123
|
-
pack_format=args.pack_format
|
124
|
-
)
|
125
|
-
except Exception as e:
|
126
|
-
error_collector.add_error(create_error(
|
127
|
-
MDLConfigurationError,
|
128
|
-
f"New command failed: {str(e)}",
|
129
|
-
suggestion="Check your arguments and try again."
|
130
|
-
))
|
138
|
+
print(f"Successfully built datapack: {output_path}")
|
139
|
+
return 0
|
131
140
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
141
|
+
except MDLCompilerError as e:
|
142
|
+
print(f"Compilation error: {e}")
|
143
|
+
return 1
|
144
|
+
|
145
|
+
|
146
|
+
def check_command(args):
|
147
|
+
"""Check MDL files for syntax errors."""
|
148
|
+
all_errors = []
|
149
|
+
|
150
|
+
for file_path in args.files:
|
151
|
+
file_path = Path(file_path)
|
152
|
+
if not file_path.exists():
|
153
|
+
print(f"Error: File '{file_path}' does not exist")
|
154
|
+
continue
|
143
155
|
|
144
|
-
|
145
|
-
|
146
|
-
|
156
|
+
try:
|
157
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
158
|
+
source = f.read()
|
159
|
+
|
160
|
+
if args.verbose:
|
161
|
+
print(f"Checking {file_path}...")
|
162
|
+
|
163
|
+
# Lex and parse to check for errors
|
164
|
+
lexer = MDLLexer(str(file_path))
|
165
|
+
tokens = list(lexer.lex(source))
|
166
|
+
|
167
|
+
parser = MDLParser(str(file_path))
|
168
|
+
ast = parser.parse(source)
|
169
|
+
|
170
|
+
if args.verbose:
|
171
|
+
print(f" ✓ {file_path} - {len(ast.functions)} functions, {len(ast.variables)} variables")
|
172
|
+
|
173
|
+
except MDLLexerError as e:
|
174
|
+
print(f"Lexer error in {file_path}: {e}")
|
175
|
+
all_errors.append(e)
|
176
|
+
except MDLParserError as e:
|
177
|
+
print(f"Parser error in {file_path}: {e}")
|
178
|
+
all_errors.append(e)
|
179
|
+
except Exception as e:
|
180
|
+
print(f"Unexpected error in {file_path}: {e}")
|
181
|
+
all_errors.append(e)
|
147
182
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
183
|
+
if all_errors:
|
184
|
+
print(f"\nFound {len(all_errors)} error(s)")
|
185
|
+
return 1
|
186
|
+
else:
|
187
|
+
print("All files passed syntax check!")
|
188
|
+
return 0
|
189
|
+
|
190
|
+
|
191
|
+
def new_command(args):
|
192
|
+
"""Create a new MDL project."""
|
193
|
+
project_name = args.project_name
|
194
|
+
pack_name = args.pack_name or project_name
|
195
|
+
pack_format = args.pack_format
|
196
|
+
|
197
|
+
# Create project directory
|
198
|
+
project_dir = Path(project_name)
|
199
|
+
if project_dir.exists():
|
200
|
+
print(f"Error: Project directory '{project_name}' already exists")
|
201
|
+
return 1
|
202
|
+
|
203
|
+
project_dir.mkdir(parents=True)
|
204
|
+
|
205
|
+
# Create main MDL file
|
206
|
+
mdl_file = project_dir / f"{project_name}.mdl"
|
207
|
+
|
208
|
+
template_content = f'''pack "{pack_name}" "Generated by MDL CLI" {pack_format};
|
209
|
+
namespace "{project_name}";
|
210
|
+
|
211
|
+
// Variables
|
212
|
+
var num counter<@s> = 0;
|
213
|
+
var num global_timer<@a> = 0;
|
214
|
+
|
215
|
+
// Main function
|
216
|
+
function {project_name}:main<@s> {{
|
217
|
+
say "Hello from {project_name}!";
|
218
|
+
|
219
|
+
// Variable example
|
220
|
+
counter<@s> = 10;
|
221
|
+
say "Counter: $counter<@s>$";
|
222
|
+
|
223
|
+
// Conditional example
|
224
|
+
if $counter<@s>$ > 5 {{
|
225
|
+
say "High counter!";
|
226
|
+
}} else {{
|
227
|
+
say "Try again!";
|
228
|
+
}}
|
229
|
+
}}
|
230
|
+
|
231
|
+
// Load function
|
232
|
+
function {project_name}:load<@s> {{
|
233
|
+
say "Datapack loaded successfully!";
|
234
|
+
}}
|
235
|
+
|
236
|
+
// Hook to run on load
|
237
|
+
on_load {project_name}:load<@s>;
|
238
|
+
'''
|
239
|
+
|
240
|
+
with open(mdl_file, 'w', encoding='utf-8') as f:
|
241
|
+
f.write(template_content)
|
242
|
+
|
243
|
+
# Create README
|
244
|
+
readme_file = project_dir / "README.md"
|
245
|
+
readme_content = f'''# {project_name}
|
246
|
+
|
247
|
+
A Minecraft datapack created with MDL (Minecraft Datapack Language).
|
248
|
+
|
249
|
+
## Getting Started
|
250
|
+
|
251
|
+
1. **Build the datapack:**
|
252
|
+
```bash
|
253
|
+
mdl build --mdl {project_name}.mdl -o dist
|
254
|
+
```
|
255
|
+
|
256
|
+
2. **Install in Minecraft:**
|
257
|
+
- Copy `dist/{project_name}/` to your world's `datapacks/` folder
|
258
|
+
- Run `/reload` in-game
|
259
|
+
|
260
|
+
3. **Run the main function:**
|
261
|
+
```bash
|
262
|
+
/function {project_name}:main
|
263
|
+
```
|
264
|
+
|
265
|
+
## Features
|
266
|
+
|
267
|
+
- **Variables**: Player-scoped counter and global timer
|
268
|
+
- **Control Flow**: If/else statements
|
269
|
+
- **Functions**: Main function and load hook
|
270
|
+
- **Automatic Execution**: Runs on datapack load
|
271
|
+
|
272
|
+
## Development
|
273
|
+
|
274
|
+
- Edit `{project_name}.mdl` to modify the datapack
|
275
|
+
- Use `mdl check {project_name}.mdl` to validate syntax
|
276
|
+
- Use `mdl build --mdl {project_name}.mdl -o dist` to rebuild
|
277
|
+
|
278
|
+
For more information, visit: https://www.mcmdl.com
|
279
|
+
'''
|
280
|
+
|
281
|
+
with open(readme_file, 'w', encoding='utf-8') as f:
|
282
|
+
f.write(readme_content)
|
283
|
+
|
284
|
+
print(f"Created new MDL project: {project_name}/")
|
285
|
+
print(f" - {mdl_file}")
|
286
|
+
print(f" - {readme_file}")
|
287
|
+
print(f"\nNext steps:")
|
288
|
+
print(f" 1. cd {project_name}")
|
289
|
+
print(f" 2. mdl build --mdl {project_name}.mdl -o dist")
|
290
|
+
print(f" 3. Copy dist/{project_name}/ to your Minecraft world's datapacks folder")
|
291
|
+
|
292
|
+
return 0
|
156
293
|
|
157
294
|
|
158
|
-
if __name__ ==
|
159
|
-
main()
|
295
|
+
if __name__ == '__main__':
|
296
|
+
sys.exit(main())
|