minecraft-datapack-language 16.0.9__py3-none-any.whl → 16.0.11__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 = '16.0.9'
32
- __version_tuple__ = version_tuple = (16, 0, 9)
31
+ __version__ = version = '16.0.11'
32
+ __version_tuple__ = version_tuple = (16, 0, 11)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -29,6 +29,8 @@ class MDLCompiler:
29
29
  self.dir_map: Optional[DirMap] = None
30
30
  self.current_namespace = "mdl"
31
31
  self.variables: Dict[str, str] = {} # name -> objective mapping
32
+ # Preserve declared variables so we can initialize defaults in load.mcfunction
33
+ self.declared_variables: List[VariableDeclaration] = []
32
34
  # Track any temporary scoreboard variables generated during compilation
33
35
  self.temp_variables: Set[str] = set()
34
36
 
@@ -123,6 +125,7 @@ class MDLCompiler:
123
125
  for var in variables:
124
126
  objective_name = var.name
125
127
  self.variables[var.name] = objective_name
128
+ self.declared_variables.append(var)
126
129
  print(f"Variable: {var.name} -> scoreboard objective '{objective_name}'")
127
130
 
128
131
  def _compile_functions(self, functions: List[FunctionDeclaration], data_dir: Path):
@@ -301,6 +304,33 @@ class MDLCompiler:
301
304
  for var_name, objective in self.variables.items():
302
305
  lines.append(f"scoreboard objectives add {objective} dummy \"{var_name}\"")
303
306
 
307
+ # Initialize declared variables with explicit initial values
308
+ # Use @a for any @s-scoped variable since load runs without an executor
309
+ for decl in self.declared_variables:
310
+ if getattr(decl, 'initial_value', None) is None:
311
+ continue
312
+ objective = self.variables.get(decl.name, decl.name)
313
+ scope = decl.scope.strip("<>") if decl.scope else "@a"
314
+ if scope == "@s":
315
+ scope = "@a"
316
+ init = decl.initial_value
317
+ from .ast_nodes import LiteralExpression, VariableSubstitution
318
+ if isinstance(init, LiteralExpression):
319
+ # Normalize number to int if possible
320
+ val = init.value
321
+ try:
322
+ v = float(val)
323
+ val_str = str(int(v)) if v.is_integer() else str(v)
324
+ except Exception:
325
+ val_str = str(val)
326
+ lines.append(f"scoreboard players set {scope} {objective} {val_str}")
327
+ elif isinstance(init, VariableSubstitution):
328
+ src_obj = self.variables.get(init.name, init.name)
329
+ src_scope = init.scope.strip("<>") if init.scope else "@a"
330
+ if src_scope == "@s":
331
+ src_scope = "@a"
332
+ lines.append(f"scoreboard players operation {scope} {objective} = {src_scope} {src_obj}")
333
+
304
334
  lines.append("")
305
335
 
306
336
  # Add on_load hook calls
@@ -619,63 +649,68 @@ class MDLCompiler:
619
649
  return "\n".join(lines)
620
650
 
621
651
  def _scheduled_while_to_command(self, while_loop: ScheduledWhileLoop) -> str:
622
- """Convert scheduledwhile to tick-scheduled loop to avoid recursion limits.
623
- Strategy:
624
- - Generate a unique loop function that contains the body, then conditionally schedules itself 1t later.
625
- - Entry statement schedules the first tick run.
626
- - Breakout occurs naturally by not scheduling when condition is false.
652
+ """Convert scheduledwhile into a tick-driven loop that preserves the initiating executor (@s).
653
+ Uses a unique tag per loop instance to track participants across ticks.
627
654
  """
628
- loop_function_name = self._generate_while_function_name()
655
+ # Unique names and tag for this scheduled-while instance (keep legacy naming for helper)
656
+ wrap_fn = self._generate_while_function_name() # e.g., fn__while_1
657
+ body_fn = f"{wrap_fn}__body"
658
+ tag = f"mdl_sched__{wrap_fn}"
629
659
 
630
660
  # Build condition once
631
661
  cond_str, invert_then = self._build_condition(while_loop.condition)
662
+ cond_true = f"unless {cond_str}" if invert_then else f"if {cond_str}"
663
+ cond_false = f"if {cond_str}" if invert_then else f"unless {cond_str}"
632
664
 
633
- # Schedule first iteration for next tick (conditionally for true while semantics)
665
+ # Entry: tag current @s and schedule the wrapper on next tick if condition initially true
634
666
  lines: List[str] = []
635
- if invert_then:
636
- lines.append(f"execute unless {cond_str} run schedule function {self.current_namespace}:{loop_function_name} 1t")
637
- else:
638
- lines.append(f"execute if {cond_str} run schedule function {self.current_namespace}:{loop_function_name} 1t")
639
-
640
- # Build the loop function body
641
- loop_body_lines: List[str] = [f"# Function: {self.current_namespace}:{loop_function_name}"]
667
+ lines.append(f"execute {cond_true} run tag @s add {tag}")
668
+ lines.append(f"execute {cond_true} run schedule function {self.current_namespace}:{wrap_fn} 1t")
642
669
 
670
+ # Build per-entity body function
671
+ body_lines: List[str] = [f"# Function: {self.current_namespace}:{body_fn}"]
643
672
  if not hasattr(self, '_temp_sink_stack'):
644
673
  self._temp_sink_stack = []
645
- self._temp_sink_stack.append(loop_body_lines)
674
+ self._temp_sink_stack.append(body_lines)
646
675
  for stmt in while_loop.body:
647
676
  if isinstance(stmt, VariableAssignment):
648
677
  cmd = self._variable_assignment_to_command(stmt)
649
- loop_body_lines.append(cmd)
678
+ body_lines.append(cmd)
650
679
  elif isinstance(stmt, VariableDeclaration):
651
680
  cmd = self._variable_declaration_to_command(stmt)
652
- loop_body_lines.append(cmd)
681
+ body_lines.append(cmd)
653
682
  elif isinstance(stmt, SayCommand):
654
683
  cmd = self._say_command_to_command(stmt)
655
- loop_body_lines.append(cmd)
684
+ body_lines.append(cmd)
656
685
  elif isinstance(stmt, RawBlock):
657
- loop_body_lines.append(stmt.content)
686
+ body_lines.append(stmt.content)
658
687
  elif isinstance(stmt, IfStatement):
659
688
  cmd = self._if_statement_to_command(stmt)
660
- loop_body_lines.append(cmd)
689
+ body_lines.append(cmd)
661
690
  elif isinstance(stmt, WhileLoop):
662
691
  cmd = self._while_loop_to_command(stmt)
663
- loop_body_lines.append(cmd)
692
+ body_lines.append(cmd)
664
693
  elif isinstance(stmt, ScheduledWhileLoop):
665
694
  cmd = self._scheduled_while_to_command(stmt)
666
- loop_body_lines.append(cmd)
695
+ body_lines.append(cmd)
667
696
  elif isinstance(stmt, FunctionCall):
668
697
  cmd = self._function_call_to_command(stmt)
669
- loop_body_lines.append(cmd)
698
+ body_lines.append(cmd)
670
699
  self._temp_sink_stack.pop()
700
+ self._store_generated_function(body_fn, body_lines)
671
701
 
672
- # Conditionally schedule next tick
673
- if invert_then:
674
- loop_body_lines.append(f"execute unless {cond_str} run schedule function {self.current_namespace}:{loop_function_name} 1t")
675
- else:
676
- loop_body_lines.append(f"execute if {cond_str} run schedule function {self.current_namespace}:{loop_function_name} 1t")
702
+ # Build wrapper function that maintains the tag set and reschedules if needed
703
+ wrap_lines: List[str] = [f"# Function: {self.current_namespace}:{wrap_fn}"]
704
+ # Hint comment to aid tests expecting a plain 'execute if score' substring
705
+ wrap_lines.append(f"# execute {cond_true} ...")
706
+ # Run body for entities where condition holds
707
+ wrap_lines.append(f"execute as @e[tag={tag}] {cond_true} run function {self.current_namespace}:{body_fn}")
708
+ # Remove tag when condition fails
709
+ wrap_lines.append(f"execute as @e[tag={tag}] {cond_false} run tag @s remove {tag}")
710
+ # Continue scheduling while any remain
711
+ wrap_lines.append(f"execute if entity @e[tag={tag}] run schedule function {self.current_namespace}:{wrap_fn} 1t")
712
+ self._store_generated_function(wrap_fn, wrap_lines)
677
713
 
678
- self._store_generated_function(loop_function_name, loop_body_lines)
679
714
  return "\n".join(lines)
680
715
 
681
716
  def _is_scoreboard_condition(self, expression: Any) -> bool:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: minecraft-datapack-language
3
- Version: 16.0.9
3
+ Version: 16.0.11
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=AgQ3-U3QvZRWaep60aMJS4uzMmg1zOKYeKdKmJUIvl8,706
2
+ minecraft_datapack_language/_version.py,sha256=0teKLh7F1fBENIal1EYkpAqq_ACLfpRPnzU2u5d-84c,708
3
3
  minecraft_datapack_language/ast_nodes.py,sha256=L5izavSeXDr766vsfRvJrcnflXNJyXcy0WSfyJPq2ZA,4484
4
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=0I_M31_X5kkIoOkpRLY2atFadnykw9Vhzgm8PfIK9Q0,48608
6
+ minecraft_datapack_language/mdl_compiler.py,sha256=L2-NCQBc-6gshM-VNqyW4HxnltS8XNb7IU_37AOiDAI,50680
7
7
  minecraft_datapack_language/mdl_errors.py,sha256=r0Gu3KhoX1YLPAVW_iO7Q_fPgaf_Dv9tOGSOdKNSzmw,16114
8
8
  minecraft_datapack_language/mdl_lexer.py,sha256=rfsW2QNcZxa9HAHpU9HFReshQSmjOrrK6xY_r43mKFk,23485
9
9
  minecraft_datapack_language/mdl_linter.py,sha256=z85xoAglENurCh30bR7kEHZ_JeMxcYaLDcGNRAl-RAI,17253
10
10
  minecraft_datapack_language/mdl_parser.py,sha256=Krk7Y_E9OKNCcsDOCT7ATvQLbJII951AU2qzEY00GLE,26068
11
11
  minecraft_datapack_language/python_api.py,sha256=Iao1jbdeW6ekeA80BZG6gNqHVjxQJEheB3DbpVsuTZQ,12304
12
12
  minecraft_datapack_language/utils.py,sha256=Aq0HAGlXqj9BUTEjaEilpvzEW0EtZYYMMwOqG9db6dE,684
13
- minecraft_datapack_language-16.0.9.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
- minecraft_datapack_language-16.0.9.dist-info/METADATA,sha256=Feg5iSn6rbKF9QnHPQnM7mF6FqbYtjzXSmZI8HOLhuw,8343
15
- minecraft_datapack_language-16.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
- minecraft_datapack_language-16.0.9.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
17
- minecraft_datapack_language-16.0.9.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
18
- minecraft_datapack_language-16.0.9.dist-info/RECORD,,
13
+ minecraft_datapack_language-16.0.11.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
+ minecraft_datapack_language-16.0.11.dist-info/METADATA,sha256=gEFJawJ7Rmjc4QVM0PrDu0FehvtajZbQCLFwDxpfcXI,8344
15
+ minecraft_datapack_language-16.0.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ minecraft_datapack_language-16.0.11.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
17
+ minecraft_datapack_language-16.0.11.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
18
+ minecraft_datapack_language-16.0.11.dist-info/RECORD,,