minecraft-datapack-language 15.4.39__py3-none-any.whl → 15.4.40__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.
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '15.4.39'
32
- __version_tuple__ = version_tuple = (15, 4, 39)
31
+ __version__ = version = '15.4.40'
32
+ __version_tuple__ = version_tuple = (15, 4, 40)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -7,6 +7,7 @@ import argparse
7
7
  import sys
8
8
  import os
9
9
  from pathlib import Path
10
+ import shutil
10
11
  from .mdl_lexer import MDLLexer
11
12
  from .mdl_parser import MDLParser
12
13
  from .mdl_compiler import MDLCompiler
@@ -37,6 +38,7 @@ Examples:
37
38
  build_parser.add_argument('-o', '--output', required=True, help='Output directory for the datapack')
38
39
  build_parser.add_argument('--verbose', action='store_true', help='Show detailed output')
39
40
  build_parser.add_argument('--wrapper', help='Optional wrapper directory name for the datapack output')
41
+ build_parser.add_argument('--no-zip', action='store_true', help='Do not create a zip archive (zip is created by default)')
40
42
 
41
43
  # Check command
42
44
  check_parser = subparsers.add_parser('check', help='Check MDL files for syntax errors')
@@ -150,6 +152,14 @@ def build_command(args):
150
152
  output_dir = output_dir / args.wrapper
151
153
  compiler = MDLCompiler()
152
154
  output_path = compiler.compile(final_ast, str(output_dir))
155
+
156
+ # Zip the datapack by default unless disabled
157
+ if not getattr(args, 'no_zip', False):
158
+ base_name = str(Path(output_path))
159
+ # Create archive next to the output directory (base_name.zip)
160
+ archive_path = shutil.make_archive(base_name, 'zip', root_dir=str(Path(output_path)))
161
+ if args.verbose:
162
+ print(f"Created archive: {archive_path}")
153
163
 
154
164
  print(f"Successfully built datapack: {output_path}")
155
165
  return 0
@@ -225,10 +225,11 @@ class MDLCompiler:
225
225
  print(f"Tag {tag.tag_type}: {tag.name} -> {tag_file} (placeholder)")
226
226
  else:
227
227
  # Write simple values list
228
- values = [f"{self.current_namespace}:{tag.name}"]
229
- # For item tags, the TagDeclaration.name may include namespace:name; use as-is
230
- if ":" in tag.name:
231
- values = [tag.name]
228
+ # For item tags, the TagDeclaration.name may include namespace:name
229
+ # The output filename should be the local name (after ':') if present
230
+ name_for_file = tag.name.split(":", 1)[1] if ":" in tag.name else tag.name
231
+ tag_file = tag_dir / f"{name_for_file}.json"
232
+ values = [tag.name if ":" in tag.name else f"{self.current_namespace}:{tag.name}"]
232
233
  tag_data = {"values": values}
233
234
  with open(tag_file, 'w') as f:
234
235
  json.dump(tag_data, f, indent=2)
@@ -249,11 +250,14 @@ class MDLCompiler:
249
250
  load_file = functions_dir / "load.mcfunction"
250
251
  with open(load_file, 'w') as f:
251
252
  f.write(load_content)
252
- # Ensure minecraft load tag points to namespace:load when needed
253
+ # Ensure minecraft load tag points to namespace:load
253
254
  tags_fn_dir = self.output_dir / "data" / "minecraft" / self.dir_map.tags_function
254
255
  tags_fn_dir.mkdir(parents=True, exist_ok=True)
255
256
  load_tag_file = tags_fn_dir / "load.json"
256
- values = [f"{self.current_namespace}:load"] if has_on_load else [f"{self.current_namespace}:load"]
257
+ # If there are explicit on_load hooks, include them; otherwise reference namespace:load
258
+ values = [f"{self.current_namespace}:load"]
259
+ if has_on_load:
260
+ values = [f"{hook.namespace}:{hook.name}" for hook in hooks if hook.hook_type == "on_load"]
257
261
  with open(load_tag_file, 'w') as f:
258
262
  json.dump({"values": values}, f, indent=2)
259
263
 
@@ -129,33 +129,108 @@ class Namespace:
129
129
  self._functions: List[FunctionDeclaration] = []
130
130
  self._hooks: List = []
131
131
 
132
- def function(self, name: str, *commands_or_builder: Union[str, Callable[["FunctionBuilder"], None]]):
133
- builder = FunctionBuilder(self._pack, self, name)
134
-
135
- # If a single callable is given, treat it as a builder lambda
132
+ def function(self, name: str, *commands_or_builder: Union[str, Callable["FunctionBuilder"], None]):
133
+ # Case 1: builder callable - use FunctionBuilder API directly
136
134
  if len(commands_or_builder) == 1 and callable(commands_or_builder[0]):
135
+ builder = FunctionBuilder(self._pack, self, name)
137
136
  commands_or_builder[0](builder)
138
- else:
139
- # Interpret simple strings: say "..."; exec ns:name; raw lines fall back to RawBlock
140
- for cmd in commands_or_builder:
141
- if not isinstance(cmd, str):
142
- continue
143
- stripped = cmd.strip().rstrip(";")
144
- if stripped.startswith("say "):
145
- msg = stripped[len("say ") :].strip()
146
- if msg.startswith("\"") and msg.endswith("\""):
147
- msg = msg[1:-1]
148
- builder.say(msg)
149
- elif stripped.startswith("exec "):
150
- target = stripped[len("exec ") :].strip()
151
- # Optional scope in angle brackets e.g., util:helper<@s>
152
- scope = None
153
- if "<" in target and target.endswith(">"):
154
- scope = target[target.index("<") :]
155
- target = target[: target.index("<")]
156
- builder.exec(target, scope)
157
- else:
158
- builder.raw(cmd)
137
+ func_node = FunctionDeclaration(namespace=self.name, name=name, scope=None, body=builder._body)
138
+ self._functions.append(func_node)
139
+ return func_node
140
+
141
+ # Case 2: string-based function body - try parsing as MDL source to build real AST
142
+ body_lines: List[str] = []
143
+ for cmd in commands_or_builder:
144
+ if isinstance(cmd, str):
145
+ body_lines.append(cmd)
146
+
147
+ if body_lines:
148
+ try:
149
+ from .mdl_parser import MDLParser
150
+ pack_decl = self._pack._pack
151
+
152
+ # Heuristic: attempt MDL parse only if there are control structures or var declarations
153
+ looks_like_mdl = any(
154
+ l.strip().startswith(("var ", "if ", "while ", "on_load", "on_tick")) or
155
+ l.strip().endswith("{") or l.strip() == "}" or "$" in l
156
+ for l in body_lines
157
+ )
158
+ if looks_like_mdl:
159
+ normalized: List[str] = []
160
+ for line in body_lines:
161
+ s = line.strip()
162
+ if not s:
163
+ continue
164
+ if s.startswith("say "):
165
+ msg = s[len("say ") :].strip()
166
+ if not (msg.startswith('"') and msg.endswith('"')):
167
+ msg = f'"{msg}"'
168
+ normalized.append(f"say {msg};")
169
+ elif s.startswith("exec "):
170
+ if not s.endswith(";"):
171
+ s = s + ";"
172
+ normalized.append(s)
173
+ elif s.startswith("var "):
174
+ if not s.endswith(";"):
175
+ s = s + ";"
176
+ normalized.append(s)
177
+ elif s.endswith("{") or s == "}" or s.endswith("}"):
178
+ normalized.append(s)
179
+ else:
180
+ # Heuristic: detect assignment like name<scope> = expr
181
+ try:
182
+ import re as _re
183
+ if _re.match(r'^[A-Za-z_][A-Za-z0-9_]*(<[^>]+>)?\s*=\s*', s):
184
+ if not s.endswith(";"):
185
+ s = s + ";"
186
+ normalized.append(s)
187
+ else:
188
+ # Unknown command; wrap as single-line raw so parser accepts it
189
+ normalized.append(f"$!raw {s} raw!$")
190
+ except Exception:
191
+ normalized.append(f"$!raw {s} raw!$")
192
+
193
+ src_lines = [
194
+ f'pack "{pack_decl.name}" "{pack_decl.description}" {pack_decl.pack_format};',
195
+ f'namespace "{self.name}";',
196
+ f'function {self.name}:{name} {{'
197
+ ]
198
+ src_lines.extend(normalized)
199
+ src_lines.append('}')
200
+ source = "\n".join(src_lines)
201
+ parser = MDLParser("<python_api>")
202
+ ast = parser.parse(source)
203
+ if ast.variables:
204
+ self._pack._variables.extend(ast.variables)
205
+ if ast.tags:
206
+ self._pack._tags.extend(ast.tags)
207
+ if ast.hooks:
208
+ self._pack._hooks.extend([(h.hook_type, f"{h.namespace}:{h.name}", h.scope) for h in ast.hooks])
209
+ if ast.functions:
210
+ fn = ast.functions[0]
211
+ self._functions.append(fn)
212
+ return fn
213
+ except Exception:
214
+ pass
215
+
216
+ # Fallback: interpret simple strings
217
+ builder = FunctionBuilder(self._pack, self, name)
218
+ for cmd in body_lines:
219
+ stripped = cmd.strip().rstrip(";")
220
+ if stripped.startswith("say "):
221
+ msg = stripped[len("say ") :].strip()
222
+ if msg.startswith('"') and msg.endswith('"'):
223
+ msg = msg[1:-1]
224
+ builder.say(msg)
225
+ elif stripped.startswith("exec "):
226
+ target = stripped[len("exec ") :].strip()
227
+ scope = None
228
+ if "<" in target and target.endswith(">"):
229
+ scope = target[target.index("<") :]
230
+ target = target[: target.index("<")]
231
+ builder.exec(target, scope)
232
+ else:
233
+ builder.raw(cmd)
159
234
 
160
235
  func_node = FunctionDeclaration(namespace=self.name, name=name, scope=None, body=builder._body)
161
236
  self._functions.append(func_node)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: minecraft-datapack-language
3
- Version: 15.4.39
3
+ Version: 15.4.40
4
4
  Summary: Compile MDL language with explicit scoping into a Minecraft datapack (1.21+ ready). Features variables, control flow, error handling, and VS Code extension.
5
5
  Project-URL: Homepage, https://www.mcmdl.com
6
6
  Project-URL: Documentation, https://www.mcmdl.com/docs
@@ -1,18 +1,18 @@
1
1
  minecraft_datapack_language/__init__.py,sha256=0KVXBE4ScRaRUrf83aA2tVB-y8A_jplyaxVvtHH6Uw0,1199
2
- minecraft_datapack_language/_version.py,sha256=9Ufx0gE3v3XMp3BFsd82w98Wj5WJy1_7_P36vYE2gnA,708
2
+ minecraft_datapack_language/_version.py,sha256=P2VVYhMLipXcQKyw7Y1OEvR4mKshcYtZAmzVwV3FZfs,708
3
3
  minecraft_datapack_language/ast_nodes.py,sha256=nbWrRz137MGMRpmnq8QkXNzrtlaCgyPEknytbkrS_M8,3899
4
- minecraft_datapack_language/cli.py,sha256=Vk35mPYm8saMUbBNRDTeoqKiLq9_do_ZeRatFWN2EQs,9824
4
+ minecraft_datapack_language/cli.py,sha256=R4QZYtox-Da9B8pr_kCg_9qc9aI-ORTah7kMkhsI5tw,10373
5
5
  minecraft_datapack_language/dir_map.py,sha256=HmxFkuvWGkzHF8o_GFb4BpuMCRc6QMw8UbmcAI8JVdY,1788
6
- minecraft_datapack_language/mdl_compiler.py,sha256=mV5qZzqriObutwsaLPmddRQdLIGJg4jiTNKg1A98Fyk,41055
6
+ minecraft_datapack_language/mdl_compiler.py,sha256=CaIHmsv4cjZa70PpderdgPlH6yNaB86WQhGyIaB0040,41396
7
7
  minecraft_datapack_language/mdl_errors.py,sha256=r0Gu3KhoX1YLPAVW_iO7Q_fPgaf_Dv9tOGSOdKNSzmw,16114
8
8
  minecraft_datapack_language/mdl_lexer.py,sha256=CjbEUpuuF4eU_ucA_WIhw6wSMcHGk2BchtQ0bLAGvwg,22033
9
9
  minecraft_datapack_language/mdl_linter.py,sha256=z85xoAglENurCh30bR7kEHZ_JeMxcYaLDcGNRAl-RAI,17253
10
10
  minecraft_datapack_language/mdl_parser.py,sha256=aQPKcmATM9BOMzO7vCXmMdxU1qjOJNLCSAKJopu5h3g,23429
11
- minecraft_datapack_language/python_api.py,sha256=ImYULwBvJ0Qb0Tf6LFyXv-gTPGZ8njX7_La0HJKuk-o,8677
11
+ minecraft_datapack_language/python_api.py,sha256=Iao1jbdeW6ekeA80BZG6gNqHVjxQJEheB3DbpVsuTZQ,12304
12
12
  minecraft_datapack_language/utils.py,sha256=Aq0HAGlXqj9BUTEjaEilpvzEW0EtZYYMMwOqG9db6dE,684
13
- minecraft_datapack_language-15.4.39.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
- minecraft_datapack_language-15.4.39.dist-info/METADATA,sha256=5eHZsdPGNCYfRdfWqW0Vy465ScEkfMpMfRhACQ7b-CI,8360
15
- minecraft_datapack_language-15.4.39.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
- minecraft_datapack_language-15.4.39.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
17
- minecraft_datapack_language-15.4.39.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
18
- minecraft_datapack_language-15.4.39.dist-info/RECORD,,
13
+ minecraft_datapack_language-15.4.40.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
+ minecraft_datapack_language-15.4.40.dist-info/METADATA,sha256=KIF4J5dORym2e-a7jCryY_SRCkqq5tyPxtCgC5vVFBA,8360
15
+ minecraft_datapack_language-15.4.40.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ minecraft_datapack_language-15.4.40.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
17
+ minecraft_datapack_language-15.4.40.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
18
+ minecraft_datapack_language-15.4.40.dist-info/RECORD,,