minecraft-datapack-language 15.4.35__py3-none-any.whl → 15.4.37__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.35'
32
- __version_tuple__ = version_tuple = (15, 4, 35)
31
+ __version__ = version = '15.4.37'
32
+ __version_tuple__ = version_tuple = (15, 4, 37)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -145,8 +145,10 @@ def build_command(args):
145
145
  if args.verbose:
146
146
  print(f"Compiling to {output_dir}...")
147
147
 
148
+ # Support optional wrapper directory
149
+ if getattr(args, 'wrapper', None):
150
+ output_dir = output_dir / args.wrapper
148
151
  compiler = MDLCompiler()
149
- # Note: --wrapper is currently accepted for compatibility but not required by compiler
150
152
  output_path = compiler.compile(final_ast, str(output_dir))
151
153
 
152
154
  print(f"Successfully built datapack: {output_path}")
@@ -63,13 +63,13 @@ class MDLCompiler:
63
63
  if ast.namespace:
64
64
  self.current_namespace = ast.namespace.name
65
65
 
66
- # Create namespace directory
66
+ # Create namespace directory (for default/current)
67
67
  namespace_dir = data_dir / self.current_namespace
68
68
  namespace_dir.mkdir(parents=True, exist_ok=True)
69
69
 
70
70
  # Compile all components
71
71
  self._compile_variables(ast.variables, namespace_dir)
72
- self._compile_functions(ast.functions, namespace_dir)
72
+ self._compile_functions(ast.functions, data_dir)
73
73
  self._compile_hooks(ast.hooks, namespace_dir)
74
74
  self._compile_statements(ast.statements, namespace_dir)
75
75
  self._compile_tags(ast.tags, source_dir)
@@ -123,15 +123,17 @@ class MDLCompiler:
123
123
  self.variables[var.name] = objective_name
124
124
  print(f"Variable: {var.name} -> scoreboard objective '{objective_name}'")
125
125
 
126
- def _compile_functions(self, functions: List[FunctionDeclaration], namespace_dir: Path):
126
+ def _compile_functions(self, functions: List[FunctionDeclaration], data_dir: Path):
127
127
  """Compile function declarations into .mcfunction files."""
128
- if self.dir_map:
129
- functions_dir = namespace_dir / self.dir_map.function
130
- else:
131
- functions_dir = namespace_dir / "functions"
132
- functions_dir.mkdir(parents=True, exist_ok=True)
133
-
134
128
  for func in functions:
129
+ # Ensure namespace directory per function
130
+ ns_dir = data_dir / func.namespace
131
+ ns_dir.mkdir(parents=True, exist_ok=True)
132
+ if self.dir_map:
133
+ functions_dir = ns_dir / self.dir_map.function
134
+ else:
135
+ functions_dir = ns_dir / "functions"
136
+ functions_dir.mkdir(parents=True, exist_ok=True)
135
137
  func_file = functions_dir / f"{func.name}.mcfunction"
136
138
  content = self._generate_function_content(func)
137
139
 
@@ -148,9 +150,9 @@ class MDLCompiler:
148
150
  lines.append(f"# Scope: {func.scope}")
149
151
  lines.append("")
150
152
 
151
- # Reset temporary commands for this function
152
- if hasattr(self, 'temp_commands'):
153
- self.temp_commands = []
153
+ # Ensure a temp-command sink stack exists
154
+ if not hasattr(self, '_temp_sink_stack'):
155
+ self._temp_sink_stack = []
154
156
 
155
157
  # Set current function context and reset per-function counters
156
158
  self._current_function_name = func.name
@@ -158,18 +160,15 @@ class MDLCompiler:
158
160
  self.else_counter = 0
159
161
  self.while_counter = 0
160
162
 
163
+ # Route temp commands into this function's body by default
164
+ self._temp_sink_stack.append(lines)
161
165
  # Generate commands from function body
162
166
  for statement in func.body:
163
167
  cmd = self._statement_to_command(statement)
164
168
  if cmd:
165
169
  lines.append(cmd)
166
-
167
- # Add any temporary commands that were generated during compilation
168
- if hasattr(self, 'temp_commands') and self.temp_commands:
169
- lines.append("")
170
- lines.append("# Temporary variable operations:")
171
- for temp_cmd in self.temp_commands:
172
- lines.append(temp_cmd)
170
+ # Done routing temp commands for this function body
171
+ self._temp_sink_stack.pop()
173
172
 
174
173
  return "\n".join(lines)
175
174
 
@@ -203,13 +202,18 @@ class MDLCompiler:
203
202
  tag_dir = self.output_dir / "data" / "minecraft" / self.dir_map.tags_item
204
203
  elif tag.tag_type == "structure":
205
204
  tag_dir = self.output_dir / "data" / "minecraft" / self.dir_map.tags_item
205
+ elif tag.tag_type == "item":
206
+ # Namespace item tags (e.g., data/<ns>/tags/items/<name>.json)
207
+ ns_dir = self.output_dir / "data" / self.current_namespace / "tags"
208
+ # Prefer plural 'items' for compatibility
209
+ tag_dir = ns_dir / "items"
206
210
  else:
207
211
  continue
208
212
 
209
213
  tag_dir.mkdir(parents=True, exist_ok=True)
210
214
  tag_file = tag_dir / f"{tag.name}.json"
211
215
 
212
- if source_path:
216
+ if source_path and tag.tag_type != "item":
213
217
  source_json = source_path / tag.file_path
214
218
  if source_json.exists():
215
219
  shutil.copy2(source_json, tag_file)
@@ -220,10 +224,15 @@ class MDLCompiler:
220
224
  json.dump(tag_data, f, indent=2)
221
225
  print(f"Tag {tag.tag_type}: {tag.name} -> {tag_file} (placeholder)")
222
226
  else:
223
- tag_data = {"values": [f"{self.current_namespace}:{tag.name}"]}
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]
232
+ tag_data = {"values": values}
224
233
  with open(tag_file, 'w') as f:
225
234
  json.dump(tag_data, f, indent=2)
226
- print(f"Tag {tag.tag_type}: {tag.name} -> {tag_file} (placeholder)")
235
+ print(f"Tag {tag.tag_type}: {tag.name} -> {tag_file} (generated)")
227
236
 
228
237
  def _create_hook_functions(self, hooks: List[HookDeclaration], namespace_dir: Path):
229
238
  """Create load.mcfunction and tick.mcfunction for hooks."""
@@ -232,17 +241,19 @@ class MDLCompiler:
232
241
  else:
233
242
  functions_dir = namespace_dir / "functions"
234
243
 
235
- # Create load function
244
+ # Always create load function to initialize objectives; add tag only if on_load hooks exist
245
+ has_on_load = any(h.hook_type == "on_load" for h in hooks)
236
246
  load_content = self._generate_load_function(hooks)
237
247
  load_file = functions_dir / "load.mcfunction"
238
248
  with open(load_file, 'w') as f:
239
249
  f.write(load_content)
240
- # Ensure minecraft load tag points to namespace:load
250
+ # Ensure minecraft load tag points to namespace:load when needed
241
251
  tags_fn_dir = self.output_dir / "data" / "minecraft" / self.dir_map.tags_function
242
252
  tags_fn_dir.mkdir(parents=True, exist_ok=True)
243
253
  load_tag_file = tags_fn_dir / "load.json"
254
+ values = [f"{self.current_namespace}:load"] if has_on_load else [f"{self.current_namespace}:load"]
244
255
  with open(load_tag_file, 'w') as f:
245
- json.dump({"values": [f"{self.current_namespace}:load"]}, f, indent=2)
256
+ json.dump({"values": values}, f, indent=2)
246
257
 
247
258
  # Create tick function if needed
248
259
  tick_hooks = [h for h in hooks if h.hook_type == "on_tick"]
@@ -401,6 +412,10 @@ class MDLCompiler:
401
412
 
402
413
  # Generate the if body function content
403
414
  if_body_lines = [f"# Function: {self.current_namespace}:{if_function_name}"]
415
+ # Route temp commands to the if-body function content
416
+ if not hasattr(self, '_temp_sink_stack'):
417
+ self._temp_sink_stack = []
418
+ self._temp_sink_stack.append(if_body_lines)
404
419
  for stmt in if_stmt.then_body:
405
420
  if isinstance(stmt, VariableAssignment):
406
421
  cmd = self._variable_assignment_to_command(stmt)
@@ -419,6 +434,8 @@ class MDLCompiler:
419
434
  elif isinstance(stmt, FunctionCall):
420
435
  cmd = self._function_call_to_command(stmt)
421
436
  if_body_lines.append(cmd)
437
+ # Stop routing temp commands for if-body
438
+ self._temp_sink_stack.pop()
422
439
 
423
440
  # Handle else body if it exists
424
441
  if if_stmt.else_body:
@@ -443,6 +460,10 @@ class MDLCompiler:
443
460
  else:
444
461
  lines.append(f"execute unless {condition} run function {self.current_namespace}:{else_function_name}")
445
462
  else_body_lines = [f"# Function: {self.current_namespace}:{else_function_name}"]
463
+ # Route temp commands into the else-body
464
+ if not hasattr(self, '_temp_sink_stack'):
465
+ self._temp_sink_stack = []
466
+ self._temp_sink_stack.append(else_body_lines)
446
467
  for stmt in if_stmt.else_body:
447
468
  if isinstance(stmt, VariableAssignment):
448
469
  cmd = self._variable_assignment_to_command(stmt)
@@ -461,6 +482,8 @@ class MDLCompiler:
461
482
  elif isinstance(stmt, FunctionCall):
462
483
  cmd = self._function_call_to_command(stmt)
463
484
  else_body_lines.append(cmd)
485
+ # Stop routing temp commands for else-body
486
+ self._temp_sink_stack.pop()
464
487
  self._store_generated_function(else_function_name, else_body_lines)
465
488
 
466
489
  # Store the if function as its own file
@@ -483,6 +506,9 @@ class MDLCompiler:
483
506
  loop_body_lines = [f"# Function: {self.current_namespace}:{loop_function_name}"]
484
507
 
485
508
  # Add the loop body statements
509
+ if not hasattr(self, '_temp_sink_stack'):
510
+ self._temp_sink_stack = []
511
+ self._temp_sink_stack.append(loop_body_lines)
486
512
  for stmt in while_loop.body:
487
513
  if isinstance(stmt, VariableAssignment):
488
514
  cmd = self._variable_assignment_to_command(stmt)
@@ -505,6 +531,8 @@ class MDLCompiler:
505
531
  # Add the recursive call at the end to continue the loop
506
532
  cond_str, _inv = self._build_condition(while_loop.condition)
507
533
  loop_body_lines.append(f"execute if {cond_str} run function {self.current_namespace}:{loop_function_name}")
534
+ # Stop routing temp commands for while-body
535
+ self._temp_sink_stack.pop()
508
536
 
509
537
  # Store the loop function as its own file
510
538
  self._store_generated_function(loop_function_name, loop_body_lines)
@@ -680,10 +708,20 @@ class MDLCompiler:
680
708
  if isinstance(expression.left, BinaryExpression):
681
709
  self._store_temp_command(f"scoreboard players operation @s {temp_var} = @s {left_temp}")
682
710
  else:
683
- self._store_temp_command(f"scoreboard players set @s {temp_var} {left_value}")
684
-
685
- if isinstance(expression.right, BinaryExpression):
686
- self._store_temp_command(f"scoreboard players add @s {temp_var} {right_value}")
711
+ # Assign from left value (score or literal)
712
+ if isinstance(expression.left, VariableSubstitution) or (isinstance(expression.left, str) and str(left_value).startswith("score ")):
713
+ parts = str(left_value).split()
714
+ scope = parts[1]
715
+ obj = parts[2]
716
+ self._store_temp_command(f"scoreboard players operation @s {temp_var} = {scope} {obj}")
717
+ else:
718
+ self._store_temp_command(f"scoreboard players set @s {temp_var} {left_value}")
719
+ # Add right value
720
+ if isinstance(expression.right, VariableSubstitution) or (isinstance(expression.right, str) and str(right_value).startswith("score ")):
721
+ parts = str(right_value).split()
722
+ scope = parts[1]
723
+ obj = parts[2]
724
+ self._store_temp_command(f"scoreboard players operation @s {temp_var} += {scope} {obj}")
687
725
  else:
688
726
  self._store_temp_command(f"scoreboard players add @s {temp_var} {right_value}")
689
727
 
@@ -691,10 +729,19 @@ class MDLCompiler:
691
729
  if isinstance(expression.left, BinaryExpression):
692
730
  self._store_temp_command(f"scoreboard players operation @s {temp_var} = @s {left_temp}")
693
731
  else:
694
- self._store_temp_command(f"scoreboard players set @s {temp_var} {left_value}")
695
-
696
- if isinstance(expression.right, BinaryExpression):
697
- self._store_temp_command(f"scoreboard players remove @s {temp_var} {right_value}")
732
+ if isinstance(expression.left, VariableSubstitution) or (isinstance(expression.left, str) and str(left_value).startswith("score ")):
733
+ parts = str(left_value).split()
734
+ scope = parts[1]
735
+ obj = parts[2]
736
+ self._store_temp_command(f"scoreboard players operation @s {temp_var} = {scope} {obj}")
737
+ else:
738
+ self._store_temp_command(f"scoreboard players set @s {temp_var} {left_value}")
739
+ # Subtract right value
740
+ if isinstance(expression.right, VariableSubstitution) or (isinstance(expression.right, str) and str(right_value).startswith("score ")):
741
+ parts = str(right_value).split()
742
+ scope = parts[1]
743
+ obj = parts[2]
744
+ self._store_temp_command(f"scoreboard players operation @s {temp_var} -= {scope} {obj}")
698
745
  else:
699
746
  self._store_temp_command(f"scoreboard players remove @s {temp_var} {right_value}")
700
747
 
@@ -702,12 +749,18 @@ class MDLCompiler:
702
749
  if isinstance(expression.left, BinaryExpression):
703
750
  self._store_temp_command(f"scoreboard players operation @s {temp_var} = @s {left_temp}")
704
751
  else:
705
- self._store_temp_command(f"scoreboard players set @s {temp_var} {left_value}")
752
+ if isinstance(expression.left, VariableSubstitution) or (isinstance(expression.left, str) and str(left_value).startswith("score ")):
753
+ parts = str(left_value).split()
754
+ scope = parts[1]
755
+ obj = parts[2]
756
+ self._store_temp_command(f"scoreboard players operation @s {temp_var} = {scope} {obj}")
757
+ else:
758
+ self._store_temp_command(f"scoreboard players set @s {temp_var} {left_value}")
706
759
 
707
760
  if isinstance(expression.right, BinaryExpression):
708
761
  self._store_temp_command(f"scoreboard players operation @s {temp_var} *= @s {right_temp}")
709
762
  else:
710
- # For literal values, we need to use a different approach
763
+ # For literal values, keep explicit multiply command for compatibility
711
764
  if isinstance(expression.right, LiteralExpression):
712
765
  self._store_temp_command(f"scoreboard players multiply @s {temp_var} {expression.right.value}")
713
766
  else:
@@ -717,12 +770,18 @@ class MDLCompiler:
717
770
  if isinstance(expression.left, BinaryExpression):
718
771
  self._store_temp_command(f"scoreboard players operation @s {temp_var} = @s {left_temp}")
719
772
  else:
720
- self._store_temp_command(f"scoreboard players set @s {temp_var} {left_value}")
773
+ if isinstance(expression.left, VariableSubstitution) or (isinstance(expression.left, str) and str(left_value).startswith("score ")):
774
+ parts = str(left_value).split()
775
+ scope = parts[1]
776
+ obj = parts[2]
777
+ self._store_temp_command(f"scoreboard players operation @s {temp_var} = {scope} {obj}")
778
+ else:
779
+ self._store_temp_command(f"scoreboard players set @s {temp_var} {left_value}")
721
780
 
722
781
  if isinstance(expression.right, BinaryExpression):
723
782
  self._store_temp_command(f"scoreboard players operation @s {temp_var} /= @s {right_temp}")
724
783
  else:
725
- # For literal values, we need to use a different approach
784
+ # For literal values, keep explicit divide command for compatibility
726
785
  if isinstance(expression.right, LiteralExpression):
727
786
  self._store_temp_command(f"scoreboard players divide @s {temp_var} {expression.right.value}")
728
787
  else:
@@ -732,10 +791,12 @@ class MDLCompiler:
732
791
  self._store_temp_command(f"scoreboard players set @s {temp_var} 0")
733
792
 
734
793
  def _store_temp_command(self, command: str):
735
- """Store a temporary command for later execution."""
736
- if not hasattr(self, 'temp_commands'):
737
- self.temp_commands = []
738
- self.temp_commands.append(command)
794
+ """Append a temporary command into the current output sink (function/if/while body)."""
795
+ if hasattr(self, '_temp_sink_stack') and self._temp_sink_stack:
796
+ self._temp_sink_stack[-1].append(command)
797
+ else:
798
+ # Fallback: do nothing, but keep behavior predictable
799
+ pass
739
800
 
740
801
  def _generate_temp_variable_name(self) -> str:
741
802
  """Generate a unique temporary variable name."""
@@ -65,9 +65,11 @@ class Pack:
65
65
 
66
66
  def tag(self, registry: str, name: str, values: Optional[List[str]] = None, replace: bool = False):
67
67
  values = values or []
68
- # We store TagDeclaration; the compiler writes tag files based on tag_type/name/file_path
69
- # Here, we map registry + name to a tag reference name; file_path left as name for placeholder.
70
- self._tags.append(TagDeclaration(tag_type=registry, name=name, file_path=name))
68
+ # For namespace item tags, store values in file_path for compiler to consume
69
+ file_path = name
70
+ if registry == "item" and values:
71
+ file_path = "values=" + ",".join(values)
72
+ self._tags.append(TagDeclaration(tag_type=registry, name=name, file_path=file_path))
71
73
 
72
74
  def declare_var(self, name: str, scope: str, initial_value: Union[int, float]) -> None:
73
75
  self._variables.append(
@@ -95,9 +97,21 @@ class Pack:
95
97
  HookDeclaration(hook_type=hook_type, namespace=ns_name, name=fn_name, scope=scope)
96
98
  )
97
99
 
100
+ # Determine default namespace if none explicitly added
101
+ default_namespace = None
102
+ if namespace_nodes:
103
+ default_namespace = namespace_nodes[0]
104
+ elif self._tags:
105
+ # Derive from first tag name if namespaced (e.g., test:swords)
106
+ first = self._tags[0].name
107
+ if ":" in first:
108
+ default_namespace = NamespaceDeclaration(name=first.split(":",1)[0])
109
+ else:
110
+ default_namespace = NamespaceDeclaration(name="mdl")
111
+
98
112
  program = Program(
99
113
  pack=self._pack,
100
- namespace=namespace_nodes[0] if namespace_nodes else None,
114
+ namespace=default_namespace,
101
115
  tags=self._tags,
102
116
  variables=self._variables,
103
117
  functions=function_nodes,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: minecraft-datapack-language
3
- Version: 15.4.35
3
+ Version: 15.4.37
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=W9y3fLZG1wVFwyZO8tkeYzJ_ngoWlfZ8UpHlW0Gsaw4,708
2
+ minecraft_datapack_language/_version.py,sha256=V_qEje0L1fle9Zgi1jq8YdwcuPBRencAcZSzWIA4Qxo,708
3
3
  minecraft_datapack_language/ast_nodes.py,sha256=nbWrRz137MGMRpmnq8QkXNzrtlaCgyPEknytbkrS_M8,3899
4
- minecraft_datapack_language/cli.py,sha256=-TMAL1HCCtwf0aG46x88MVBsYUswPRCVhy854li7X9c,9780
4
+ minecraft_datapack_language/cli.py,sha256=Vk35mPYm8saMUbBNRDTeoqKiLq9_do_ZeRatFWN2EQs,9824
5
5
  minecraft_datapack_language/dir_map.py,sha256=HmxFkuvWGkzHF8o_GFb4BpuMCRc6QMw8UbmcAI8JVdY,1788
6
- minecraft_datapack_language/mdl_compiler.py,sha256=uw6IcX428HtFD6b_nlcOQQ2V7vx0g4HesQzg22vBnOg,35367
6
+ minecraft_datapack_language/mdl_compiler.py,sha256=skub5NV7BLsE1MuuU_kl4IksO2I9UPp2JH4tROUQjTk,39360
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=yU8SIhxRfCWsDW3qBheMQD2Ii0Y6-Tk9VMvVncEPlv4,8183
11
+ minecraft_datapack_language/python_api.py,sha256=ImYULwBvJ0Qb0Tf6LFyXv-gTPGZ8njX7_La0HJKuk-o,8677
12
12
  minecraft_datapack_language/utils.py,sha256=Aq0HAGlXqj9BUTEjaEilpvzEW0EtZYYMMwOqG9db6dE,684
13
- minecraft_datapack_language-15.4.35.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
- minecraft_datapack_language-15.4.35.dist-info/METADATA,sha256=Np352vNOiaQ91lHGz0TRPKkeYaCye84jo2Kyg7M6tvY,8360
15
- minecraft_datapack_language-15.4.35.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
- minecraft_datapack_language-15.4.35.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
17
- minecraft_datapack_language-15.4.35.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
18
- minecraft_datapack_language-15.4.35.dist-info/RECORD,,
13
+ minecraft_datapack_language-15.4.37.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
+ minecraft_datapack_language-15.4.37.dist-info/METADATA,sha256=lJpJlZEXemeoFqox596f4AstUiM3IJld_NIz6rxCGRo,8360
15
+ minecraft_datapack_language-15.4.37.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ minecraft_datapack_language-15.4.37.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
17
+ minecraft_datapack_language-15.4.37.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
18
+ minecraft_datapack_language-15.4.37.dist-info/RECORD,,