minecraft-datapack-language 15.1.63__py3-none-any.whl → 15.1.65__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/cli_build.py +73 -14
- minecraft_datapack_language/cli_utils.py +31 -13
- {minecraft_datapack_language-15.1.63.dist-info → minecraft_datapack_language-15.1.65.dist-info}/METADATA +1 -1
- {minecraft_datapack_language-15.1.63.dist-info → minecraft_datapack_language-15.1.65.dist-info}/RECORD +9 -9
- {minecraft_datapack_language-15.1.63.dist-info → minecraft_datapack_language-15.1.65.dist-info}/WHEEL +0 -0
- {minecraft_datapack_language-15.1.63.dist-info → minecraft_datapack_language-15.1.65.dist-info}/entry_points.txt +0 -0
- {minecraft_datapack_language-15.1.63.dist-info → minecraft_datapack_language-15.1.65.dist-info}/licenses/LICENSE +0 -0
- {minecraft_datapack_language-15.1.63.dist-info → minecraft_datapack_language-15.1.65.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 = '15.1.
|
32
|
-
__version_tuple__ = version_tuple = (15, 1,
|
31
|
+
__version__ = version = '15.1.65'
|
32
|
+
__version_tuple__ = version_tuple = (15, 1, 65)
|
33
33
|
|
34
34
|
__commit_id__ = commit_id = None
|
@@ -193,6 +193,9 @@ def _generate_load_function(scoreboard_commands: List[str], output_dir: Path, na
|
|
193
193
|
"""Generate the load function with scoreboard setup."""
|
194
194
|
load_content = []
|
195
195
|
|
196
|
+
# Add armor stand setup for server-side operations
|
197
|
+
load_content.append("execute unless entity @e[type=armor_stand,tag=mdl_server,limit=1] run summon armor_stand ~ 320 ~ {Tags:[\"mdl_server\"],Invisible:1b,Marker:1b,NoGravity:1b,Invulnerable:1b}")
|
198
|
+
|
196
199
|
# Add scoreboard objectives
|
197
200
|
load_content.extend(scoreboard_commands)
|
198
201
|
|
@@ -213,15 +216,20 @@ def _process_say_command_with_variables(content: str, selector: str) -> str:
|
|
213
216
|
"""Process say command content with variable substitution, converting to tellraw with score components."""
|
214
217
|
import re
|
215
218
|
|
219
|
+
# Clean up the content - remove quotes if present
|
220
|
+
content = content.strip()
|
221
|
+
if content.startswith('"') and content.endswith('"'):
|
222
|
+
content = content[1:-1] # Remove surrounding quotes
|
223
|
+
|
216
224
|
# Find all variable references like $variable$ or $variable<selector>$
|
217
225
|
var_pattern = r'\$([^$]+)\$'
|
218
226
|
matches = re.findall(var_pattern, content)
|
219
227
|
|
220
228
|
if not matches:
|
221
229
|
# No variables, return simple tellraw
|
222
|
-
return f'tellraw @a [{{"text":{content}}}]'
|
230
|
+
return f'tellraw @a [{{"text":"{content}"}}]'
|
223
231
|
|
224
|
-
# Split content by variable references
|
232
|
+
# Split content by variable references while preserving the structure
|
225
233
|
parts = re.split(var_pattern, content)
|
226
234
|
|
227
235
|
# Build tellraw components
|
@@ -244,8 +252,8 @@ def _process_say_command_with_variables(content: str, selector: str) -> str:
|
|
244
252
|
var_selector = var_parts[1][:-1] # Remove trailing >
|
245
253
|
components.append(f'{{"score":{{"name":"{var_selector}","objective":"{base_var}"}}}}')
|
246
254
|
else:
|
247
|
-
# Simple variable: $variable$
|
248
|
-
components.append(f'{{"score":{{"name":"
|
255
|
+
# Simple variable: $variable$ - use server armor stand
|
256
|
+
components.append(f'{{"score":{{"name":"@e[type=armor_stand,tag=mdl_server,limit=1]","objective":"{var_name}"}}}}')
|
249
257
|
|
250
258
|
var_index += 1
|
251
259
|
|
@@ -274,6 +282,10 @@ def _process_statement(statement: Any, namespace: str, function_name: str, state
|
|
274
282
|
# Convert to Minecraft tellraw format
|
275
283
|
processed_command = _process_say_command_with_variables(content, selector)
|
276
284
|
commands.append(processed_command)
|
285
|
+
elif command.startswith('tellraw @a '):
|
286
|
+
# Fix extra space in tellraw commands
|
287
|
+
fixed_command = command.replace('tellraw @ a ', 'tellraw @a ')
|
288
|
+
commands.append(fixed_command)
|
277
289
|
else:
|
278
290
|
# Process other commands normally
|
279
291
|
processed_command = _process_variable_substitutions(command, selector)
|
@@ -285,26 +297,50 @@ def _process_statement(statement: Any, namespace: str, function_name: str, state
|
|
285
297
|
|
286
298
|
# Handle different value types
|
287
299
|
if isinstance(value, int):
|
288
|
-
commands.append(f"scoreboard players set {
|
300
|
+
commands.append(f"scoreboard players set {selector} {var_name} {value}")
|
289
301
|
elif isinstance(value, str) and value.startswith('$') and value.endswith('$'):
|
290
302
|
# Variable reference
|
291
303
|
ref_var = value[1:-1] # Remove $ symbols
|
292
|
-
commands.append(f"scoreboard players operation {
|
304
|
+
commands.append(f"scoreboard players operation {selector} {var_name} = {selector} {ref_var}")
|
293
305
|
elif hasattr(value, '__class__') and 'BinaryExpression' in str(value.__class__):
|
294
306
|
# Handle complex expressions (BinaryExpression, etc.)
|
295
|
-
#
|
296
|
-
|
307
|
+
# Convert to proper Minecraft scoreboard commands
|
308
|
+
if hasattr(value, 'left') and hasattr(value, 'right') and hasattr(value, 'operator'):
|
309
|
+
left = value.left
|
310
|
+
right = value.right
|
311
|
+
operator = value.operator
|
312
|
+
|
313
|
+
# Handle different operators
|
314
|
+
if operator == 'PLUS':
|
315
|
+
if hasattr(left, 'name') and hasattr(right, 'value'):
|
316
|
+
# counter = counter + 1
|
317
|
+
commands.append(f"scoreboard players add {selector} {var_name} {right.value}")
|
318
|
+
else:
|
319
|
+
# Complex case - use operation
|
320
|
+
commands.append(f"# Complex addition: {var_name} = {left} + {right}")
|
321
|
+
elif operator == 'MINUS':
|
322
|
+
if hasattr(left, 'name') and hasattr(right, 'value'):
|
323
|
+
# health = health - 10
|
324
|
+
commands.append(f"scoreboard players remove {selector} {var_name} {right.value}")
|
325
|
+
else:
|
326
|
+
# Complex case - use operation
|
327
|
+
commands.append(f"# Complex subtraction: {var_name} = {left} - {right}")
|
328
|
+
else:
|
329
|
+
# Other operators - use operation
|
330
|
+
commands.append(f"# Complex operation: {var_name} = {left} {operator} {right}")
|
331
|
+
else:
|
332
|
+
commands.append(f"# Complex assignment: {var_name} = {value}")
|
297
333
|
else:
|
298
334
|
# Handle LiteralExpression and other value types
|
299
335
|
try:
|
300
336
|
if hasattr(value, 'value'):
|
301
337
|
# LiteralExpression case
|
302
338
|
num_value = int(value.value)
|
303
|
-
commands.append(f"scoreboard players set {
|
339
|
+
commands.append(f"scoreboard players set {selector} {var_name} {num_value}")
|
304
340
|
else:
|
305
341
|
# Direct value case
|
306
342
|
num_value = int(value)
|
307
|
-
commands.append(f"scoreboard players set {
|
343
|
+
commands.append(f"scoreboard players set {selector} {var_name} {num_value}")
|
308
344
|
except (ValueError, TypeError):
|
309
345
|
# If we can't convert to int, add a placeholder
|
310
346
|
commands.append(f"# Assignment: {var_name} = {value}")
|
@@ -328,7 +364,11 @@ def _process_statement(statement: Any, namespace: str, function_name: str, state
|
|
328
364
|
|
329
365
|
# Write conditional function
|
330
366
|
if if_commands:
|
331
|
-
|
367
|
+
# Use the output directory from build context
|
368
|
+
if hasattr(build_context, 'output_dir'):
|
369
|
+
if_dir = build_context.output_dir / "data" / namespace / "function"
|
370
|
+
else:
|
371
|
+
if_dir = Path(f"data/{namespace}/function")
|
332
372
|
ensure_dir(str(if_dir))
|
333
373
|
with open(if_dir / f"{if_func_name}.mcfunction", 'w', encoding='utf-8') as f:
|
334
374
|
f.write('\n'.join(if_commands))
|
@@ -410,11 +450,17 @@ def _generate_function_file(ast: Dict[str, Any], output_dir: Path, namespace: st
|
|
410
450
|
|
411
451
|
# Write function file
|
412
452
|
if function_commands:
|
453
|
+
# Add armor stand setup to the beginning of each function
|
454
|
+
final_commands = []
|
455
|
+
final_commands.append("execute unless entity @e[type=armor_stand,tag=mdl_server,limit=1] run summon armor_stand ~ 320 ~ {Tags:[\"mdl_server\"],Invisible:1b,Marker:1b,NoGravity:1b,Invulnerable:1b}")
|
456
|
+
final_commands.append("")
|
457
|
+
final_commands.extend(function_commands)
|
458
|
+
|
413
459
|
func_dir = output_dir / "data" / namespace / "function"
|
414
460
|
ensure_dir(str(func_dir))
|
415
461
|
|
416
462
|
with open(func_dir / f"{func_name}.mcfunction", 'w', encoding='utf-8') as f:
|
417
|
-
f.write('\n'.join(
|
463
|
+
f.write('\n'.join(final_commands))
|
418
464
|
|
419
465
|
if verbose:
|
420
466
|
print(f"Generated function: {namespace}:{func_name}")
|
@@ -442,6 +488,11 @@ def _generate_hook_files(ast: Dict[str, Any], output_dir: Path, namespace: str,
|
|
442
488
|
if hook['hook_type'] == 'load':
|
443
489
|
load_values.append(hook['function_name'])
|
444
490
|
|
491
|
+
# Add pack-specific load function if pack name is available
|
492
|
+
if 'pack' in ast and 'name' in ast['pack']:
|
493
|
+
pack_name = ast['pack']['name']
|
494
|
+
load_values.append(f"{pack_name}:load")
|
495
|
+
|
445
496
|
load_tag_content = {
|
446
497
|
"values": load_values
|
447
498
|
}
|
@@ -540,7 +591,11 @@ def _process_while_loop_recursion(while_statement, namespace: str, function_name
|
|
540
591
|
|
541
592
|
# Write loop body function
|
542
593
|
if body_commands:
|
543
|
-
|
594
|
+
# Use the output directory from build context
|
595
|
+
if hasattr(build_context, 'output_dir'):
|
596
|
+
func_dir = build_context.output_dir / "data" / namespace / "function"
|
597
|
+
else:
|
598
|
+
func_dir = Path(f"data/{namespace}/function")
|
544
599
|
ensure_dir(str(func_dir))
|
545
600
|
with open(func_dir / f"{loop_body_func_name}.mcfunction", 'w', encoding='utf-8') as f:
|
546
601
|
f.write('\n'.join(body_commands))
|
@@ -586,7 +641,11 @@ def _process_while_loop_schedule(while_statement, namespace: str, function_name:
|
|
586
641
|
|
587
642
|
# Write loop body function
|
588
643
|
if body_commands:
|
589
|
-
|
644
|
+
# Use the output directory from build context
|
645
|
+
if hasattr(build_context, 'output_dir'):
|
646
|
+
func_dir = build_context.output_dir / "data" / namespace / "function"
|
647
|
+
else:
|
648
|
+
func_dir = Path(f"data/{namespace}/function")
|
590
649
|
ensure_dir(str(func_dir))
|
591
650
|
with open(func_dir / f"{loop_body_func_name}.mcfunction", 'w', encoding='utf-8') as f:
|
592
651
|
f.write('\n'.join(body_commands))
|
@@ -119,6 +119,24 @@ def _convert_condition_to_minecraft_syntax(condition: str, selector: str = "@s")
|
|
119
119
|
# Remove extra whitespace and normalize
|
120
120
|
condition = condition.strip()
|
121
121
|
|
122
|
+
# Handle variable substitution in conditions (e.g., "$value$ > 3")
|
123
|
+
import re
|
124
|
+
var_pattern = r'\$([^$]+)\$'
|
125
|
+
|
126
|
+
# Replace variable references with proper scoreboard syntax
|
127
|
+
def replace_var(match):
|
128
|
+
var_name = match.group(1)
|
129
|
+
# Remove scope selector if present
|
130
|
+
if '<' in var_name and var_name.endswith('>'):
|
131
|
+
var_parts = var_name.split('<', 1)
|
132
|
+
base_var = var_parts[0]
|
133
|
+
return f"@e[type=armor_stand,tag=mdl_server,limit=1] {base_var}"
|
134
|
+
else:
|
135
|
+
return f"@e[type=armor_stand,tag=mdl_server,limit=1] {var_name}"
|
136
|
+
|
137
|
+
# Apply variable substitution
|
138
|
+
condition = re.sub(var_pattern, replace_var)
|
139
|
+
|
122
140
|
# Handle common patterns
|
123
141
|
if '==' in condition:
|
124
142
|
var1, var2 = condition.split('==', 1)
|
@@ -128,10 +146,10 @@ def _convert_condition_to_minecraft_syntax(condition: str, selector: str = "@s")
|
|
128
146
|
# Check if var2 is a number
|
129
147
|
try:
|
130
148
|
value = int(var2)
|
131
|
-
return f"score {var1}
|
149
|
+
return f"score {var1} matches {value}"
|
132
150
|
except ValueError:
|
133
151
|
# Both are variables, compare them
|
134
|
-
return f"score {var1}
|
152
|
+
return f"score {var1} = {var2}"
|
135
153
|
|
136
154
|
elif '!=' in condition:
|
137
155
|
var1, var2 = condition.split('!=', 1)
|
@@ -140,9 +158,9 @@ def _convert_condition_to_minecraft_syntax(condition: str, selector: str = "@s")
|
|
140
158
|
|
141
159
|
try:
|
142
160
|
value = int(var2)
|
143
|
-
return f"score {var1}
|
161
|
+
return f"score {var1} matches ..{value-1} {value+1}.."
|
144
162
|
except ValueError:
|
145
|
-
return f"score {var1}
|
163
|
+
return f"score {var1} != {var2}"
|
146
164
|
|
147
165
|
elif '>' in condition:
|
148
166
|
var1, var2 = condition.split('>', 1)
|
@@ -151,9 +169,9 @@ def _convert_condition_to_minecraft_syntax(condition: str, selector: str = "@s")
|
|
151
169
|
|
152
170
|
try:
|
153
171
|
value = int(var2)
|
154
|
-
return f"score {var1}
|
172
|
+
return f"score {var1} matches {value+1}.."
|
155
173
|
except ValueError:
|
156
|
-
return f"score {var1}
|
174
|
+
return f"score {var1} > {var2}"
|
157
175
|
|
158
176
|
elif '<' in condition:
|
159
177
|
var1, var2 = condition.split('<', 1)
|
@@ -162,9 +180,9 @@ def _convert_condition_to_minecraft_syntax(condition: str, selector: str = "@s")
|
|
162
180
|
|
163
181
|
try:
|
164
182
|
value = int(var2)
|
165
|
-
return f"score {var1}
|
183
|
+
return f"score {var1} matches ..{value-1}"
|
166
184
|
except ValueError:
|
167
|
-
return f"score {var1}
|
185
|
+
return f"score {var1} < {var2}"
|
168
186
|
|
169
187
|
elif '>=' in condition:
|
170
188
|
var1, var2 = condition.split('>=', 1)
|
@@ -173,9 +191,9 @@ def _convert_condition_to_minecraft_syntax(condition: str, selector: str = "@s")
|
|
173
191
|
|
174
192
|
try:
|
175
193
|
value = int(var2)
|
176
|
-
return f"score {var1}
|
194
|
+
return f"score {var1} matches {value}.."
|
177
195
|
except ValueError:
|
178
|
-
return f"score {var1}
|
196
|
+
return f"score {var1} >= {var2}"
|
179
197
|
|
180
198
|
elif '<=' in condition:
|
181
199
|
var1, var2 = condition.split('<=', 1)
|
@@ -184,12 +202,12 @@ def _convert_condition_to_minecraft_syntax(condition: str, selector: str = "@s")
|
|
184
202
|
|
185
203
|
try:
|
186
204
|
value = int(var2)
|
187
|
-
return f"score {var1}
|
205
|
+
return f"score {var1} matches ..{value}"
|
188
206
|
except ValueError:
|
189
|
-
return f"score {var1}
|
207
|
+
return f"score {var1} <= {var2}"
|
190
208
|
|
191
209
|
# Default: treat as a variable that should be non-zero
|
192
|
-
return f"score {condition}
|
210
|
+
return f"score {condition} matches 1.."
|
193
211
|
|
194
212
|
|
195
213
|
def _find_mdl_files(directory: Path) -> List[Path]:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: minecraft-datapack-language
|
3
|
-
Version: 15.1.
|
3
|
+
Version: 15.1.65
|
4
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
5
|
Project-URL: Homepage, https://www.mcmdl.com
|
6
6
|
Project-URL: Documentation, https://www.mcmdl.com/docs
|
@@ -1,12 +1,12 @@
|
|
1
1
|
minecraft_datapack_language/__init__.py,sha256=i-qCchbe5b2Fshgc6yCU9mddOLs2UBt9SAcLqfUIrT0,606
|
2
|
-
minecraft_datapack_language/_version.py,sha256=
|
2
|
+
minecraft_datapack_language/_version.py,sha256=7XSJDjuzb6Ytmg80BCgGO_aHPtsA2iZo3CHgHS1KD24,708
|
3
3
|
minecraft_datapack_language/ast_nodes.py,sha256=pgjI2Nlap3ixFPgWqGSkqncG9zB91h5BKgRjtcJqMew,2118
|
4
4
|
minecraft_datapack_language/cli.py,sha256=p5A_tEEXugN2NhQFbbgfwi4FxbWYD91RWeKR_A3Vuec,6263
|
5
|
-
minecraft_datapack_language/cli_build.py,sha256=
|
5
|
+
minecraft_datapack_language/cli_build.py,sha256=UwAGGnL7PyTnBZ9ArIrPcTx5-mysy_HGWA_f9-AjUak,39959
|
6
6
|
minecraft_datapack_language/cli_check.py,sha256=bPq9gHsxQ1CIiftkrAtRCifWkVAyjp5c8Oay2NNQ1qs,6277
|
7
7
|
minecraft_datapack_language/cli_help.py,sha256=jUTHUQBONAZKVTdQK9tNPXq4c_6xpsafNOvHDjkEldg,12243
|
8
8
|
minecraft_datapack_language/cli_new.py,sha256=uaKH0VBC43XBt_Hztc35-BfC9bYlsDdLbAfe_42rrtI,8235
|
9
|
-
minecraft_datapack_language/cli_utils.py,sha256=
|
9
|
+
minecraft_datapack_language/cli_utils.py,sha256=OF64njFa_19qGJ-1EBMI8btMs8OUi-0wGoFAQo6525U,9775
|
10
10
|
minecraft_datapack_language/dir_map.py,sha256=HmxFkuvWGkzHF8o_GFb4BpuMCRc6QMw8UbmcAI8JVdY,1788
|
11
11
|
minecraft_datapack_language/expression_processor.py,sha256=GN6cuRNvgI8TrV6YnEHrA9P0X-ACTT7rCBh4WlOPjSI,20140
|
12
12
|
minecraft_datapack_language/linter.py,sha256=7UqbygC5JPCGg-BSOq65NB2xEJBu_OUOYIIgmHItO2M,16567
|
@@ -16,9 +16,9 @@ minecraft_datapack_language/mdl_linter.py,sha256=z85xoAglENurCh30bR7kEHZ_JeMxcYa
|
|
16
16
|
minecraft_datapack_language/mdl_parser_js.py,sha256=4VMWx6O7A10afTzjGnnwL_Sh52osIO84ObqHp8KoDZw,38677
|
17
17
|
minecraft_datapack_language/pack.py,sha256=nYiXQ3jgJlDfc4m-65f7C2LFhDRioaUU_XVy6Na4SJI,34625
|
18
18
|
minecraft_datapack_language/utils.py,sha256=Aq0HAGlXqj9BUTEjaEilpvzEW0EtZYYMMwOqG9db6dE,684
|
19
|
-
minecraft_datapack_language-15.1.
|
20
|
-
minecraft_datapack_language-15.1.
|
21
|
-
minecraft_datapack_language-15.1.
|
22
|
-
minecraft_datapack_language-15.1.
|
23
|
-
minecraft_datapack_language-15.1.
|
24
|
-
minecraft_datapack_language-15.1.
|
19
|
+
minecraft_datapack_language-15.1.65.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
20
|
+
minecraft_datapack_language-15.1.65.dist-info/METADATA,sha256=r8kJIxQ6Z_eslXNyagKOtfz_Cq5vX_1f6U9Q33saoRw,35230
|
21
|
+
minecraft_datapack_language-15.1.65.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
22
|
+
minecraft_datapack_language-15.1.65.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
|
23
|
+
minecraft_datapack_language-15.1.65.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
|
24
|
+
minecraft_datapack_language-15.1.65.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|