minecraft-datapack-language 16.0.3__py3-none-any.whl → 16.0.5__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/_version.py +2 -2
- minecraft_datapack_language/ast_nodes.py +7 -0
- minecraft_datapack_language/mdl_compiler.py +59 -1
- minecraft_datapack_language/mdl_lexer.py +2 -0
- minecraft_datapack_language/mdl_parser.py +17 -1
- {minecraft_datapack_language-16.0.3.dist-info → minecraft_datapack_language-16.0.5.dist-info}/METADATA +1 -1
- minecraft_datapack_language-16.0.5.dist-info/RECORD +18 -0
- minecraft_datapack_language-16.0.3.dist-info/RECORD +0 -18
- {minecraft_datapack_language-16.0.3.dist-info → minecraft_datapack_language-16.0.5.dist-info}/WHEEL +0 -0
- {minecraft_datapack_language-16.0.3.dist-info → minecraft_datapack_language-16.0.5.dist-info}/entry_points.txt +0 -0
- {minecraft_datapack_language-16.0.3.dist-info → minecraft_datapack_language-16.0.5.dist-info}/licenses/LICENSE +0 -0
- {minecraft_datapack_language-16.0.3.dist-info → minecraft_datapack_language-16.0.5.dist-info}/top_level.txt +0 -0
@@ -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.
|
32
|
-
__version_tuple__ = version_tuple = (16, 0,
|
31
|
+
__version__ = version = '16.0.5'
|
32
|
+
__version_tuple__ = version_tuple = (16, 0, 5)
|
33
33
|
|
34
34
|
__commit_id__ = commit_id = None
|
@@ -94,6 +94,13 @@ class WhileLoop(ASTNode):
|
|
94
94
|
body: List[ASTNode]
|
95
95
|
|
96
96
|
|
97
|
+
@dataclass
|
98
|
+
class ScheduledWhileLoop(ASTNode):
|
99
|
+
"""Scheduled-while loop that iterates via Minecraft's schedule command each tick."""
|
100
|
+
condition: Any # Expression
|
101
|
+
body: List[ASTNode]
|
102
|
+
|
103
|
+
|
97
104
|
@dataclass
|
98
105
|
class HookDeclaration(ASTNode):
|
99
106
|
"""Hook declaration (on_load, on_tick)."""
|
@@ -11,7 +11,7 @@ from typing import Dict, List, Any, Optional
|
|
11
11
|
from .ast_nodes import (
|
12
12
|
Program, PackDeclaration, NamespaceDeclaration, TagDeclaration,
|
13
13
|
VariableDeclaration, VariableAssignment, VariableSubstitution, FunctionDeclaration,
|
14
|
-
FunctionCall, IfStatement, WhileLoop, HookDeclaration, RawBlock, MacroLine,
|
14
|
+
FunctionCall, IfStatement, WhileLoop, ScheduledWhileLoop, HookDeclaration, RawBlock, MacroLine,
|
15
15
|
SayCommand, BinaryExpression, LiteralExpression, ParenthesizedExpression
|
16
16
|
)
|
17
17
|
from .dir_map import get_dir_map, DirMap
|
@@ -345,6 +345,8 @@ class MDLCompiler:
|
|
345
345
|
return self._if_statement_to_command(statement)
|
346
346
|
elif isinstance(statement, WhileLoop):
|
347
347
|
return self._while_loop_to_command(statement)
|
348
|
+
elif isinstance(statement, ScheduledWhileLoop):
|
349
|
+
return self._scheduled_while_to_command(statement)
|
348
350
|
elif isinstance(statement, FunctionCall):
|
349
351
|
return self._function_call_to_command(statement)
|
350
352
|
else:
|
@@ -607,6 +609,62 @@ class MDLCompiler:
|
|
607
609
|
self._store_generated_function(loop_function_name, loop_body_lines)
|
608
610
|
|
609
611
|
return "\n".join(lines)
|
612
|
+
|
613
|
+
def _scheduled_while_to_command(self, while_loop: ScheduledWhileLoop) -> str:
|
614
|
+
"""Convert scheduledwhile to tick-scheduled loop to avoid recursion limits.
|
615
|
+
Strategy:
|
616
|
+
- Generate a unique loop function that contains the body, then conditionally schedules itself 1t later.
|
617
|
+
- Entry statement schedules the first tick run.
|
618
|
+
- Breakout occurs naturally by not scheduling when condition is false.
|
619
|
+
"""
|
620
|
+
loop_function_name = self._generate_while_function_name()
|
621
|
+
|
622
|
+
# Schedule first iteration for next tick
|
623
|
+
lines: List[str] = []
|
624
|
+
lines.append(f"schedule function {self.current_namespace}:{loop_function_name} 1t")
|
625
|
+
|
626
|
+
# Build the loop function body
|
627
|
+
loop_body_lines: List[str] = [f"# Function: {self.current_namespace}:{loop_function_name}"]
|
628
|
+
|
629
|
+
if not hasattr(self, '_temp_sink_stack'):
|
630
|
+
self._temp_sink_stack = []
|
631
|
+
self._temp_sink_stack.append(loop_body_lines)
|
632
|
+
for stmt in while_loop.body:
|
633
|
+
if isinstance(stmt, VariableAssignment):
|
634
|
+
cmd = self._variable_assignment_to_command(stmt)
|
635
|
+
loop_body_lines.append(cmd)
|
636
|
+
elif isinstance(stmt, VariableDeclaration):
|
637
|
+
cmd = self._variable_declaration_to_command(stmt)
|
638
|
+
loop_body_lines.append(cmd)
|
639
|
+
elif isinstance(stmt, SayCommand):
|
640
|
+
cmd = self._say_command_to_command(stmt)
|
641
|
+
loop_body_lines.append(cmd)
|
642
|
+
elif isinstance(stmt, RawBlock):
|
643
|
+
loop_body_lines.append(stmt.content)
|
644
|
+
elif isinstance(stmt, IfStatement):
|
645
|
+
cmd = self._if_statement_to_command(stmt)
|
646
|
+
loop_body_lines.append(cmd)
|
647
|
+
elif isinstance(stmt, WhileLoop):
|
648
|
+
cmd = self._while_loop_to_command(stmt)
|
649
|
+
loop_body_lines.append(cmd)
|
650
|
+
elif isinstance(stmt, ScheduledWhileLoop):
|
651
|
+
cmd = self._scheduled_while_to_command(stmt)
|
652
|
+
loop_body_lines.append(cmd)
|
653
|
+
elif isinstance(stmt, FunctionCall):
|
654
|
+
cmd = self._function_call_to_command(stmt)
|
655
|
+
loop_body_lines.append(cmd)
|
656
|
+
self._temp_sink_stack.pop()
|
657
|
+
|
658
|
+
cond_str, invert_then = self._build_condition(while_loop.condition)
|
659
|
+
if invert_then:
|
660
|
+
# Inverted means schedule unless condition (NOT desired). We want continue-when-true.
|
661
|
+
# cond_str represents equality in inverted case; continue when not(cond) → use unless.
|
662
|
+
loop_body_lines.append(f"execute unless {cond_str} run schedule function {self.current_namespace}:{loop_function_name} 1t")
|
663
|
+
else:
|
664
|
+
loop_body_lines.append(f"execute if {cond_str} run schedule function {self.current_namespace}:{loop_function_name} 1t")
|
665
|
+
|
666
|
+
self._store_generated_function(loop_function_name, loop_body_lines)
|
667
|
+
return "\n".join(lines)
|
610
668
|
|
611
669
|
def _is_scoreboard_condition(self, expression: Any) -> bool:
|
612
670
|
"""Check if an expression is a scoreboard comparison."""
|
@@ -33,6 +33,7 @@ class TokenType:
|
|
33
33
|
IF = "IF"
|
34
34
|
ELSE = "ELSE"
|
35
35
|
WHILE = "WHILE"
|
36
|
+
SCHEDULED_WHILE = "SCHEDULED_WHILE"
|
36
37
|
ON_LOAD = "ON_LOAD"
|
37
38
|
ON_TICK = "ON_TICK"
|
38
39
|
EXEC = "EXEC"
|
@@ -599,6 +600,7 @@ class MDLLexer:
|
|
599
600
|
'if': TokenType.IF,
|
600
601
|
'else': TokenType.ELSE,
|
601
602
|
'while': TokenType.WHILE,
|
603
|
+
'scheduledwhile': TokenType.SCHEDULED_WHILE,
|
602
604
|
'on_load': TokenType.ON_LOAD,
|
603
605
|
'on_tick': TokenType.ON_TICK,
|
604
606
|
'exec': TokenType.EXEC,
|
@@ -9,7 +9,7 @@ from .mdl_errors import MDLParserError
|
|
9
9
|
from .ast_nodes import (
|
10
10
|
ASTNode, Program, PackDeclaration, NamespaceDeclaration, TagDeclaration,
|
11
11
|
VariableDeclaration, VariableAssignment, VariableSubstitution, FunctionDeclaration,
|
12
|
-
FunctionCall, IfStatement, WhileLoop, HookDeclaration, RawBlock, MacroLine,
|
12
|
+
FunctionCall, IfStatement, WhileLoop, ScheduledWhileLoop, HookDeclaration, RawBlock, MacroLine,
|
13
13
|
SayCommand, TellrawCommand, ExecuteCommand, ScoreboardCommand,
|
14
14
|
BinaryExpression, UnaryExpression, ParenthesizedExpression, LiteralExpression,
|
15
15
|
ScopeSelector
|
@@ -87,6 +87,8 @@ class MDLParser:
|
|
87
87
|
statements.append(self._parse_if_statement())
|
88
88
|
elif self._peek().type == TokenType.WHILE:
|
89
89
|
statements.append(self._parse_while_loop())
|
90
|
+
elif self._peek().type == TokenType.SCHEDULED_WHILE:
|
91
|
+
statements.append(self._parse_scheduled_while_loop())
|
90
92
|
elif self._peek().type == TokenType.DOLLAR and self._peek(1).type == TokenType.EXCLAMATION:
|
91
93
|
statements.append(self._parse_raw_block())
|
92
94
|
elif self._peek().type == TokenType.IDENTIFIER:
|
@@ -348,6 +350,18 @@ class MDLParser:
|
|
348
350
|
self._expect(TokenType.RBRACE, "Expected '}' to end while body")
|
349
351
|
|
350
352
|
return WhileLoop(condition=condition, body=body)
|
353
|
+
|
354
|
+
def _parse_scheduled_while_loop(self) -> ScheduledWhileLoop:
|
355
|
+
"""Parse scheduledwhile loop: scheduledwhile condition { body }"""
|
356
|
+
self._expect(TokenType.SCHEDULED_WHILE, "Expected 'scheduledwhile' keyword")
|
357
|
+
|
358
|
+
condition = self._parse_expression()
|
359
|
+
|
360
|
+
self._expect(TokenType.LBRACE, "Expected '{' to start while body")
|
361
|
+
body = self._parse_block()
|
362
|
+
self._expect(TokenType.RBRACE, "Expected '}' to end while body")
|
363
|
+
|
364
|
+
return ScheduledWhileLoop(condition=condition, body=body)
|
351
365
|
|
352
366
|
def _parse_hook_declaration(self) -> HookDeclaration:
|
353
367
|
"""Parse hook declaration: on_load/on_tick namespace:name<scope>;"""
|
@@ -524,6 +538,8 @@ class MDLParser:
|
|
524
538
|
statements.append(self._parse_if_statement())
|
525
539
|
elif self._peek().type == TokenType.WHILE:
|
526
540
|
statements.append(self._parse_while_loop())
|
541
|
+
elif self._peek().type == TokenType.SCHEDULED_WHILE:
|
542
|
+
statements.append(self._parse_scheduled_while_loop())
|
527
543
|
elif self._peek().type == TokenType.EXEC:
|
528
544
|
statements.append(self._parse_function_call())
|
529
545
|
elif self._peek().type == TokenType.MACRO_LINE:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: minecraft-datapack-language
|
3
|
-
Version: 16.0.
|
3
|
+
Version: 16.0.5
|
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
|
@@ -0,0 +1,18 @@
|
|
1
|
+
minecraft_datapack_language/__init__.py,sha256=0KVXBE4ScRaRUrf83aA2tVB-y8A_jplyaxVvtHH6Uw0,1199
|
2
|
+
minecraft_datapack_language/_version.py,sha256=5eUnbGX41cw4x_iyQa8Ni4HiMgC19n416l0EMUwLHfw,706
|
3
|
+
minecraft_datapack_language/ast_nodes.py,sha256=L5izavSeXDr766vsfRvJrcnflXNJyXcy0WSfyJPq2ZA,4484
|
4
|
+
minecraft_datapack_language/cli.py,sha256=R4QZYtox-Da9B8pr_kCg_9qc9aI-ORTah7kMkhsI5tw,10373
|
5
|
+
minecraft_datapack_language/dir_map.py,sha256=HmxFkuvWGkzHF8o_GFb4BpuMCRc6QMw8UbmcAI8JVdY,1788
|
6
|
+
minecraft_datapack_language/mdl_compiler.py,sha256=rYNaxvVRje2ot1RaUHibF4HItxca2MovntH0kjx65Vc,47808
|
7
|
+
minecraft_datapack_language/mdl_errors.py,sha256=r0Gu3KhoX1YLPAVW_iO7Q_fPgaf_Dv9tOGSOdKNSzmw,16114
|
8
|
+
minecraft_datapack_language/mdl_lexer.py,sha256=rfsW2QNcZxa9HAHpU9HFReshQSmjOrrK6xY_r43mKFk,23485
|
9
|
+
minecraft_datapack_language/mdl_linter.py,sha256=z85xoAglENurCh30bR7kEHZ_JeMxcYaLDcGNRAl-RAI,17253
|
10
|
+
minecraft_datapack_language/mdl_parser.py,sha256=Krk7Y_E9OKNCcsDOCT7ATvQLbJII951AU2qzEY00GLE,26068
|
11
|
+
minecraft_datapack_language/python_api.py,sha256=Iao1jbdeW6ekeA80BZG6gNqHVjxQJEheB3DbpVsuTZQ,12304
|
12
|
+
minecraft_datapack_language/utils.py,sha256=Aq0HAGlXqj9BUTEjaEilpvzEW0EtZYYMMwOqG9db6dE,684
|
13
|
+
minecraft_datapack_language-16.0.5.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
14
|
+
minecraft_datapack_language-16.0.5.dist-info/METADATA,sha256=K2CNC7E-v1wQA-cvRREQfc8ClamgHzNPxJyWY9K2Olc,8343
|
15
|
+
minecraft_datapack_language-16.0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
16
|
+
minecraft_datapack_language-16.0.5.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
|
17
|
+
minecraft_datapack_language-16.0.5.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
|
18
|
+
minecraft_datapack_language-16.0.5.dist-info/RECORD,,
|
@@ -1,18 +0,0 @@
|
|
1
|
-
minecraft_datapack_language/__init__.py,sha256=0KVXBE4ScRaRUrf83aA2tVB-y8A_jplyaxVvtHH6Uw0,1199
|
2
|
-
minecraft_datapack_language/_version.py,sha256=ZzL1luJQ5Xsyk9nl0-sOfrvRBFL0a9MDofeSfFIrSVI,706
|
3
|
-
minecraft_datapack_language/ast_nodes.py,sha256=UzUxKLkjBisUd5Gu7sAiNXIIPIjNoRzELq4LfIFcnSY,4290
|
4
|
-
minecraft_datapack_language/cli.py,sha256=R4QZYtox-Da9B8pr_kCg_9qc9aI-ORTah7kMkhsI5tw,10373
|
5
|
-
minecraft_datapack_language/dir_map.py,sha256=HmxFkuvWGkzHF8o_GFb4BpuMCRc6QMw8UbmcAI8JVdY,1788
|
6
|
-
minecraft_datapack_language/mdl_compiler.py,sha256=Fny9kxjN1X8ghAGjcASOEX7Uf1VwVhbSctLR3z4j9r4,44757
|
7
|
-
minecraft_datapack_language/mdl_errors.py,sha256=r0Gu3KhoX1YLPAVW_iO7Q_fPgaf_Dv9tOGSOdKNSzmw,16114
|
8
|
-
minecraft_datapack_language/mdl_lexer.py,sha256=dVwdgUmdQI7EJaFtoKZpq6rj5156YVjt44mMee-MDIs,23388
|
9
|
-
minecraft_datapack_language/mdl_linter.py,sha256=z85xoAglENurCh30bR7kEHZ_JeMxcYaLDcGNRAl-RAI,17253
|
10
|
-
minecraft_datapack_language/mdl_parser.py,sha256=axyjdrcgqeOpbmWolasiIZAjV_RpFaP5QiafLPXAhms,25223
|
11
|
-
minecraft_datapack_language/python_api.py,sha256=Iao1jbdeW6ekeA80BZG6gNqHVjxQJEheB3DbpVsuTZQ,12304
|
12
|
-
minecraft_datapack_language/utils.py,sha256=Aq0HAGlXqj9BUTEjaEilpvzEW0EtZYYMMwOqG9db6dE,684
|
13
|
-
minecraft_datapack_language-16.0.3.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
14
|
-
minecraft_datapack_language-16.0.3.dist-info/METADATA,sha256=MvNegD-ZES76aokgaBpxOC0aJi1Hl2PQsdahx2QU1wQ,8343
|
15
|
-
minecraft_datapack_language-16.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
16
|
-
minecraft_datapack_language-16.0.3.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
|
17
|
-
minecraft_datapack_language-16.0.3.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
|
18
|
-
minecraft_datapack_language-16.0.3.dist-info/RECORD,,
|
{minecraft_datapack_language-16.0.3.dist-info → minecraft_datapack_language-16.0.5.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|