amulet-core 2.0a5__cp312-cp312-macosx_10_13_universal2.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.

Potentially problematic release.


This version of amulet-core might be problematic. Click here for more details.

Files changed (210) hide show
  1. amulet/__init__.cpython-312-darwin.so +0 -0
  2. amulet/__init__.pyi +30 -0
  3. amulet/__pyinstaller/__init__.py +2 -0
  4. amulet/__pyinstaller/hook-amulet.py +4 -0
  5. amulet/_init.py +28 -0
  6. amulet/_version.py +21 -0
  7. amulet/biome.cpp +36 -0
  8. amulet/biome.hpp +43 -0
  9. amulet/biome.pyi +77 -0
  10. amulet/block.cpp +435 -0
  11. amulet/block.hpp +119 -0
  12. amulet/block.pyi +273 -0
  13. amulet/block_entity.cpp +12 -0
  14. amulet/block_entity.hpp +56 -0
  15. amulet/block_entity.pyi +80 -0
  16. amulet/chunk.cpp +16 -0
  17. amulet/chunk.hpp +99 -0
  18. amulet/chunk.pyi +30 -0
  19. amulet/chunk_/components/biome.py +155 -0
  20. amulet/chunk_/components/block_entity.py +117 -0
  21. amulet/chunk_/components/entity.py +64 -0
  22. amulet/chunk_/components/height_2d.py +16 -0
  23. amulet/chunk_components.pyi +95 -0
  24. amulet/collections.pyi +37 -0
  25. amulet/data_types.py +29 -0
  26. amulet/entity.py +180 -0
  27. amulet/errors.py +63 -0
  28. amulet/game/__init__.py +7 -0
  29. amulet/game/_game.py +152 -0
  30. amulet/game/_universal/__init__.py +1 -0
  31. amulet/game/_universal/_biome.py +17 -0
  32. amulet/game/_universal/_block.py +47 -0
  33. amulet/game/_universal/_version.py +68 -0
  34. amulet/game/abc/__init__.py +22 -0
  35. amulet/game/abc/_block_specification.py +150 -0
  36. amulet/game/abc/biome.py +213 -0
  37. amulet/game/abc/block.py +331 -0
  38. amulet/game/abc/game_version_container.py +25 -0
  39. amulet/game/abc/json_interface.py +27 -0
  40. amulet/game/abc/version.py +44 -0
  41. amulet/game/bedrock/__init__.py +1 -0
  42. amulet/game/bedrock/_biome.py +35 -0
  43. amulet/game/bedrock/_block.py +42 -0
  44. amulet/game/bedrock/_version.py +165 -0
  45. amulet/game/java/__init__.py +2 -0
  46. amulet/game/java/_biome.py +35 -0
  47. amulet/game/java/_block.py +60 -0
  48. amulet/game/java/_version.py +176 -0
  49. amulet/game/translate/__init__.py +12 -0
  50. amulet/game/translate/_functions/__init__.py +15 -0
  51. amulet/game/translate/_functions/_code_functions/__init__.py +0 -0
  52. amulet/game/translate/_functions/_code_functions/_text.py +553 -0
  53. amulet/game/translate/_functions/_code_functions/banner_pattern.py +67 -0
  54. amulet/game/translate/_functions/_code_functions/bedrock_chest_connection.py +152 -0
  55. amulet/game/translate/_functions/_code_functions/bedrock_moving_block_pos.py +88 -0
  56. amulet/game/translate/_functions/_code_functions/bedrock_sign.py +152 -0
  57. amulet/game/translate/_functions/_code_functions/bedrock_skull_rotation.py +16 -0
  58. amulet/game/translate/_functions/_code_functions/custom_name.py +146 -0
  59. amulet/game/translate/_functions/_frozen.py +66 -0
  60. amulet/game/translate/_functions/_state.py +54 -0
  61. amulet/game/translate/_functions/_typing.py +98 -0
  62. amulet/game/translate/_functions/abc.py +116 -0
  63. amulet/game/translate/_functions/carry_nbt.py +160 -0
  64. amulet/game/translate/_functions/carry_properties.py +80 -0
  65. amulet/game/translate/_functions/code.py +143 -0
  66. amulet/game/translate/_functions/map_block_name.py +66 -0
  67. amulet/game/translate/_functions/map_nbt.py +111 -0
  68. amulet/game/translate/_functions/map_properties.py +93 -0
  69. amulet/game/translate/_functions/multiblock.py +112 -0
  70. amulet/game/translate/_functions/new_block.py +42 -0
  71. amulet/game/translate/_functions/new_entity.py +43 -0
  72. amulet/game/translate/_functions/new_nbt.py +206 -0
  73. amulet/game/translate/_functions/new_properties.py +64 -0
  74. amulet/game/translate/_functions/sequence.py +51 -0
  75. amulet/game/translate/_functions/walk_input_nbt.py +331 -0
  76. amulet/game/translate/_translator.py +433 -0
  77. amulet/item.py +75 -0
  78. amulet/level/__init__.pyi +27 -0
  79. amulet/level/_load.py +100 -0
  80. amulet/level/abc/__init__.py +12 -0
  81. amulet/level/abc/_chunk_handle.py +335 -0
  82. amulet/level/abc/_dimension.py +86 -0
  83. amulet/level/abc/_history/__init__.py +1 -0
  84. amulet/level/abc/_history/_cache.py +224 -0
  85. amulet/level/abc/_history/_history_manager.py +291 -0
  86. amulet/level/abc/_level/__init__.py +5 -0
  87. amulet/level/abc/_level/_compactable_level.py +10 -0
  88. amulet/level/abc/_level/_creatable_level.py +29 -0
  89. amulet/level/abc/_level/_disk_level.py +17 -0
  90. amulet/level/abc/_level/_level.py +453 -0
  91. amulet/level/abc/_level/_loadable_level.py +42 -0
  92. amulet/level/abc/_player_storage.py +7 -0
  93. amulet/level/abc/_raw_level.py +187 -0
  94. amulet/level/abc/_registry.py +40 -0
  95. amulet/level/bedrock/__init__.py +2 -0
  96. amulet/level/bedrock/_chunk_handle.py +19 -0
  97. amulet/level/bedrock/_dimension.py +22 -0
  98. amulet/level/bedrock/_level.py +187 -0
  99. amulet/level/bedrock/_raw/__init__.py +5 -0
  100. amulet/level/bedrock/_raw/_actor_counter.py +53 -0
  101. amulet/level/bedrock/_raw/_chunk.py +54 -0
  102. amulet/level/bedrock/_raw/_chunk_decode.py +668 -0
  103. amulet/level/bedrock/_raw/_chunk_encode.py +602 -0
  104. amulet/level/bedrock/_raw/_constant.py +9 -0
  105. amulet/level/bedrock/_raw/_dimension.py +343 -0
  106. amulet/level/bedrock/_raw/_level.py +463 -0
  107. amulet/level/bedrock/_raw/_level_dat.py +90 -0
  108. amulet/level/bedrock/_raw/_typing.py +6 -0
  109. amulet/level/bedrock/_raw/leveldb_chunk_versions.py +83 -0
  110. amulet/level/bedrock/chunk/__init__.py +1 -0
  111. amulet/level/bedrock/chunk/_chunk.py +126 -0
  112. amulet/level/bedrock/chunk/components/__init__.py +0 -0
  113. amulet/level/bedrock/chunk/components/chunk_version.py +12 -0
  114. amulet/level/bedrock/chunk/components/finalised_state.py +13 -0
  115. amulet/level/bedrock/chunk/components/raw_chunk.py +15 -0
  116. amulet/level/construction/__init__.py +0 -0
  117. amulet/level/java/__init__.pyi +21 -0
  118. amulet/level/java/_chunk_handle.py +17 -0
  119. amulet/level/java/_chunk_handle.pyi +15 -0
  120. amulet/level/java/_dimension.py +20 -0
  121. amulet/level/java/_dimension.pyi +13 -0
  122. amulet/level/java/_level.py +184 -0
  123. amulet/level/java/_level.pyi +120 -0
  124. amulet/level/java/_raw/__init__.pyi +19 -0
  125. amulet/level/java/_raw/_chunk.pyi +23 -0
  126. amulet/level/java/_raw/_chunk_decode.py +561 -0
  127. amulet/level/java/_raw/_chunk_encode.py +463 -0
  128. amulet/level/java/_raw/_constant.py +9 -0
  129. amulet/level/java/_raw/_constant.pyi +20 -0
  130. amulet/level/java/_raw/_data_pack/__init__.py +2 -0
  131. amulet/level/java/_raw/_data_pack/__init__.pyi +8 -0
  132. amulet/level/java/_raw/_data_pack/data_pack.py +241 -0
  133. amulet/level/java/_raw/_data_pack/data_pack.pyi +197 -0
  134. amulet/level/java/_raw/_data_pack/data_pack_manager.py +77 -0
  135. amulet/level/java/_raw/_data_pack/data_pack_manager.pyi +75 -0
  136. amulet/level/java/_raw/_dimension.py +86 -0
  137. amulet/level/java/_raw/_dimension.pyi +72 -0
  138. amulet/level/java/_raw/_level.py +507 -0
  139. amulet/level/java/_raw/_level.pyi +238 -0
  140. amulet/level/java/_raw/_typing.py +3 -0
  141. amulet/level/java/_raw/_typing.pyi +5 -0
  142. amulet/level/java/anvil/__init__.py +2 -0
  143. amulet/level/java/anvil/__init__.pyi +11 -0
  144. amulet/level/java/anvil/_dimension.py +170 -0
  145. amulet/level/java/anvil/_dimension.pyi +109 -0
  146. amulet/level/java/anvil/_region.py +421 -0
  147. amulet/level/java/anvil/_region.pyi +197 -0
  148. amulet/level/java/anvil/_sector_manager.py +223 -0
  149. amulet/level/java/anvil/_sector_manager.pyi +142 -0
  150. amulet/level/java/chunk.pyi +81 -0
  151. amulet/level/java/chunk_/_chunk.py +260 -0
  152. amulet/level/java/chunk_/components/inhabited_time.py +12 -0
  153. amulet/level/java/chunk_/components/last_update.py +12 -0
  154. amulet/level/java/chunk_/components/legacy_version.py +12 -0
  155. amulet/level/java/chunk_/components/light_populated.py +12 -0
  156. amulet/level/java/chunk_/components/named_height_2d.py +37 -0
  157. amulet/level/java/chunk_/components/status.py +11 -0
  158. amulet/level/java/chunk_/components/terrain_populated.py +12 -0
  159. amulet/level/java/chunk_components.pyi +22 -0
  160. amulet/level/java/long_array.pyi +38 -0
  161. amulet/level/java_forge/__init__.py +0 -0
  162. amulet/level/mcstructure/__init__.py +0 -0
  163. amulet/level/nbt/__init__.py +0 -0
  164. amulet/level/schematic/__init__.py +0 -0
  165. amulet/level/sponge_schematic/__init__.py +0 -0
  166. amulet/level/temporary_level/__init__.py +1 -0
  167. amulet/level/temporary_level/_level.py +16 -0
  168. amulet/palette/__init__.pyi +8 -0
  169. amulet/palette/biome_palette.pyi +45 -0
  170. amulet/palette/block_palette.pyi +45 -0
  171. amulet/player.py +64 -0
  172. amulet/py.typed +0 -0
  173. amulet/selection/__init__.py +2 -0
  174. amulet/selection/abstract_selection.py +342 -0
  175. amulet/selection/box.py +852 -0
  176. amulet/selection/group.py +481 -0
  177. amulet/utils/__init__.pyi +28 -0
  178. amulet/utils/call_spec/__init__.py +24 -0
  179. amulet/utils/call_spec/__init__.pyi +53 -0
  180. amulet/utils/call_spec/_call_spec.py +262 -0
  181. amulet/utils/call_spec/_call_spec.pyi +272 -0
  182. amulet/utils/format_utils.py +41 -0
  183. amulet/utils/generator.py +18 -0
  184. amulet/utils/matrix.py +243 -0
  185. amulet/utils/matrix.pyi +177 -0
  186. amulet/utils/numpy.pyi +11 -0
  187. amulet/utils/numpy_helpers.py +19 -0
  188. amulet/utils/shareable_lock.py +335 -0
  189. amulet/utils/shareable_lock.pyi +190 -0
  190. amulet/utils/signal/__init__.py +10 -0
  191. amulet/utils/signal/__init__.pyi +25 -0
  192. amulet/utils/signal/_signal.py +228 -0
  193. amulet/utils/signal/_signal.pyi +84 -0
  194. amulet/utils/task_manager.py +235 -0
  195. amulet/utils/task_manager.pyi +168 -0
  196. amulet/utils/typed_property.py +111 -0
  197. amulet/utils/typing.py +4 -0
  198. amulet/utils/typing.pyi +6 -0
  199. amulet/utils/weakref.py +70 -0
  200. amulet/utils/weakref.pyi +50 -0
  201. amulet/utils/world_utils.py +102 -0
  202. amulet/utils/world_utils.pyi +109 -0
  203. amulet/version.cpp +136 -0
  204. amulet/version.hpp +142 -0
  205. amulet/version.pyi +94 -0
  206. amulet_core-2.0a5.dist-info/METADATA +103 -0
  207. amulet_core-2.0a5.dist-info/RECORD +210 -0
  208. amulet_core-2.0a5.dist-info/WHEEL +5 -0
  209. amulet_core-2.0a5.dist-info/entry_points.txt +2 -0
  210. amulet_core-2.0a5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,98 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Union, Type, TypeAlias
4
+ from collections.abc import Iterable
5
+
6
+ from amulet_nbt import (
7
+ ByteTag,
8
+ ShortTag,
9
+ IntTag,
10
+ LongTag,
11
+ FloatTag,
12
+ DoubleTag,
13
+ StringTag,
14
+ ListTag,
15
+ CompoundTag,
16
+ ByteArrayTag,
17
+ IntArrayTag,
18
+ LongArrayTag,
19
+ )
20
+
21
+ NBTTagT: TypeAlias = Union[
22
+ ByteTag,
23
+ ShortTag,
24
+ IntTag,
25
+ LongTag,
26
+ FloatTag,
27
+ DoubleTag,
28
+ ByteArrayTag,
29
+ StringTag,
30
+ ListTag,
31
+ CompoundTag,
32
+ IntArrayTag,
33
+ LongArrayTag,
34
+ ]
35
+
36
+ NBTTagClasses = (
37
+ ByteTag,
38
+ ShortTag,
39
+ IntTag,
40
+ LongTag,
41
+ FloatTag,
42
+ DoubleTag,
43
+ ByteArrayTag,
44
+ StringTag,
45
+ ListTag,
46
+ CompoundTag,
47
+ IntArrayTag,
48
+ LongArrayTag,
49
+ )
50
+
51
+ NBTTagClsT: TypeAlias = Union[
52
+ Type[ByteTag],
53
+ Type[ShortTag],
54
+ Type[IntTag],
55
+ Type[LongTag],
56
+ Type[FloatTag],
57
+ Type[DoubleTag],
58
+ Type[ByteArrayTag],
59
+ Type[StringTag],
60
+ Type[ListTag],
61
+ Type[CompoundTag],
62
+ Type[IntArrayTag],
63
+ Type[LongArrayTag],
64
+ ]
65
+
66
+ StrToNBTCls = {
67
+ "byte": ByteTag,
68
+ "short": ShortTag,
69
+ "int": IntTag,
70
+ "long": LongTag,
71
+ "float": FloatTag,
72
+ "double": DoubleTag,
73
+ "byte_array": ByteArrayTag,
74
+ "string": StringTag,
75
+ "list": ListTag,
76
+ "compound": CompoundTag,
77
+ "int_array": IntArrayTag,
78
+ "long_array": LongArrayTag,
79
+ }
80
+
81
+ NBTClsToStr = {
82
+ ByteTag: "byte",
83
+ ShortTag: "short",
84
+ IntTag: "int",
85
+ LongTag: "long",
86
+ FloatTag: "float",
87
+ DoubleTag: "double",
88
+ ByteArrayTag: "byte_array",
89
+ StringTag: "string",
90
+ ListTag: "list",
91
+ CompoundTag: "compound",
92
+ IntArrayTag: "int_array",
93
+ LongArrayTag: "long_array",
94
+ }
95
+
96
+
97
+ NBTPathElement: TypeAlias = tuple[str | int, NBTTagClsT]
98
+ NBTPath: TypeAlias = tuple[NBTPathElement, ...]
@@ -0,0 +1,116 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Protocol, cast, Self, ClassVar
4
+ from abc import ABC, abstractmethod, ABCMeta
5
+
6
+ from amulet_nbt import (
7
+ read_snbt,
8
+ NamedTag,
9
+ CompoundTag,
10
+ ListTag,
11
+ )
12
+
13
+ from amulet.block import PropertyValueType
14
+ from amulet.game.abc import JSONInterface, JSONCompatible
15
+ from ._state import SrcData, StateData, DstData
16
+ from ._typing import NBTPath, NBTTagT
17
+
18
+
19
+ def immutable_from_snbt(snbt: str) -> PropertyValueType:
20
+ val = read_snbt(snbt)
21
+ assert isinstance(val, PropertyValueType)
22
+ return val
23
+
24
+
25
+ def follow_nbt_path(
26
+ nbt: NamedTag, nbt_path: tuple[str, type[CompoundTag] | type[ListTag], NBTPath]
27
+ ) -> NBTTagT | None:
28
+ outer_name, outer_type, path = nbt_path
29
+ if nbt.name != outer_name or not isinstance(nbt.tag, outer_type):
30
+ return None
31
+ tag = nbt.tag
32
+ for key, tag_cls in path:
33
+ if isinstance(key, int) and isinstance(tag, ListTag) and key < len(tag):
34
+ tag = tag[key]
35
+ elif isinstance(key, str) and isinstance(tag, CompoundTag) and key in tag:
36
+ tag = tag[key]
37
+ else:
38
+ return None
39
+ if not isinstance(tag, tag_cls):
40
+ return None
41
+ return cast(NBTTagT | None, tag)
42
+
43
+
44
+ def translation_function_from_json(
45
+ data: JSONCompatible,
46
+ ) -> AbstractBaseTranslationFunction:
47
+ if isinstance(data, list):
48
+ func_cls = _translation_functions["sequence"]
49
+ return func_cls.from_json(data)
50
+ elif isinstance(data, dict):
51
+ function_name = data["function"]
52
+ assert isinstance(function_name, str)
53
+ func_cls = _translation_functions[function_name]
54
+ return func_cls.from_json(data)
55
+ else:
56
+ raise TypeError
57
+
58
+
59
+ _translation_functions: dict[str, type[AbstractBaseTranslationFunction]] = {}
60
+
61
+
62
+ class Data(Protocol):
63
+ def __hash__(self) -> int: ...
64
+
65
+ def __eq__(self, other: Any) -> bool: ...
66
+
67
+
68
+ class CacheMeta(ABCMeta):
69
+ """This modifies the construction of the instance to always return a cached instance, if one exists."""
70
+
71
+ def __call__(cls: type[AbstractBaseTranslationFunction], *args: Any, **kwargs: Any) -> AbstractBaseTranslationFunction: # type: ignore
72
+ obj = cls.__new__(cls)
73
+ obj.__init__(*args, **kwargs) # type: ignore
74
+ return cls._instances.setdefault(obj, obj)
75
+
76
+
77
+ class AbstractBaseTranslationFunction(JSONInterface, metaclass=CacheMeta):
78
+ Name: ClassVar[str] = ""
79
+ _instances: ClassVar[dict[Self, Self]]
80
+ _hash: int | None
81
+
82
+ def __init__(self) -> None:
83
+ self._hash = None
84
+
85
+ def __init_subclass__(cls, **kwargs: Any) -> None:
86
+ if cls.Name == "":
87
+ raise RuntimeError(f"Name attribute has not been set for {cls}")
88
+ if cls.Name in _translation_functions:
89
+ raise RuntimeError(
90
+ f"A translation function with name {cls.Name} already exists."
91
+ )
92
+ _translation_functions[cls.Name] = cls
93
+
94
+ @abstractmethod
95
+ def __reduce__(self) -> Any:
96
+ raise NotImplementedError
97
+
98
+ @abstractmethod
99
+ def _data(self) -> Data:
100
+ raise NotImplementedError
101
+
102
+ def __bool__(self) -> bool:
103
+ return True
104
+
105
+ def __hash__(self) -> int:
106
+ if self._hash is None:
107
+ self._hash = hash(self._data())
108
+ return self._hash
109
+
110
+ def __eq__(self, other: Any) -> bool:
111
+ return isinstance(other, self.__class__) and self._data() == other._data()
112
+
113
+ @abstractmethod
114
+ def run(self, src: SrcData, state: StateData, dst: DstData) -> None:
115
+ """Run the translation function"""
116
+ raise NotImplementedError
@@ -0,0 +1,160 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Self, Any
4
+
5
+ from amulet_nbt import CompoundTag, ListTag, AbstractBaseNumericTag
6
+
7
+ from .abc import (
8
+ AbstractBaseTranslationFunction,
9
+ Data,
10
+ follow_nbt_path,
11
+ )
12
+ from amulet.game.abc import JSONCompatible, JSONDict
13
+ from ._typing import NBTTagClsT, NBTClsToStr, StrToNBTCls, NBTPath
14
+ from ._state import SrcData, StateData, DstData
15
+
16
+
17
+ class CarryNBT(AbstractBaseTranslationFunction):
18
+ # Class variables
19
+ Name = "carry_nbt"
20
+ _instances = {}
21
+
22
+ # Instance variables
23
+ _outer_name: str
24
+ _outer_type: type[CompoundTag] | type[ListTag]
25
+ _path: NBTPath | None
26
+ _key: str | int | None
27
+ _tag_cls: NBTTagClsT | None
28
+
29
+ def __init__(
30
+ self,
31
+ outer_name: str = "",
32
+ outer_type: type[CompoundTag] | type[ListTag] = CompoundTag,
33
+ path: NBTPath | None = None,
34
+ key: str | int | None = None,
35
+ tag_cls: NBTTagClsT | None = None,
36
+ ) -> None:
37
+ super().__init__()
38
+ self._outer_name = outer_name
39
+ self._outer_type = outer_type
40
+ self._path = path
41
+ self._key = key
42
+ self._tag_cls = tag_cls
43
+
44
+ def __reduce__(self) -> Any:
45
+ return CarryNBT, (
46
+ self._outer_name,
47
+ self._outer_type,
48
+ self._path,
49
+ self._key,
50
+ self._tag_cls,
51
+ )
52
+
53
+ def _data(self) -> Data:
54
+ return (
55
+ self._outer_name,
56
+ self._outer_type,
57
+ self._path,
58
+ self._key,
59
+ self._tag_cls,
60
+ )
61
+
62
+ @classmethod
63
+ def from_json(cls, data: JSONCompatible) -> Self:
64
+ assert isinstance(data, dict)
65
+ assert data.get("function") == "carry_nbt"
66
+ options = data.get("options", {})
67
+ assert isinstance(options, dict)
68
+ outer_name = options.get("outer_name", "")
69
+ assert isinstance(outer_name, str)
70
+ outer_type_name = options.get("outer_type", "compound")
71
+ outer_type: type[CompoundTag] | type[ListTag]
72
+ if outer_type_name == "compound":
73
+ outer_type = CompoundTag
74
+ elif outer_type_name == "list":
75
+ outer_type = ListTag
76
+ else:
77
+ raise RuntimeError
78
+ assert isinstance(outer_type_name, str)
79
+ path: NBTPath | None
80
+ if "path" in options:
81
+ raw_path = options["path"]
82
+ assert isinstance(raw_path, list)
83
+ path_ = []
84
+ for item in raw_path:
85
+ assert isinstance(item, list) and len(item) == 2
86
+ key, cls_name = item
87
+ assert isinstance(key, str | int)
88
+ nbt_cls: type[CompoundTag] | type[ListTag]
89
+ if cls_name == "compound":
90
+ nbt_cls = CompoundTag
91
+ elif cls_name == "list":
92
+ nbt_cls = ListTag
93
+ else:
94
+ raise RuntimeError
95
+ path_.append((key, nbt_cls))
96
+ path = NBTPath(path_)
97
+ else:
98
+ path = None
99
+ key = options.get("key", None)
100
+ if key is not None:
101
+ assert isinstance(key, str | int)
102
+ cls_name = options.get("type", None)
103
+ if cls_name is None:
104
+ nbt_type = None
105
+ else:
106
+ assert isinstance(cls_name, str)
107
+ nbt_type = StrToNBTCls[cls_name]
108
+
109
+ return cls(
110
+ outer_name,
111
+ outer_type,
112
+ path,
113
+ key,
114
+ nbt_type,
115
+ )
116
+
117
+ def to_json(self) -> JSONDict:
118
+ options: JSONDict = {}
119
+ if self._outer_name:
120
+ options["outer_name"] = self._outer_name
121
+ if self._outer_type is not CompoundTag:
122
+ options["outer_type"] = NBTClsToStr[self._outer_type]
123
+ if self._path is not None:
124
+ options["path"] = [[key, NBTClsToStr[cls]] for key, cls in self._path]
125
+ if self._key is not None:
126
+ options["key"] = self._key
127
+ if self._tag_cls is not None:
128
+ options["type"] = NBTClsToStr[self._tag_cls]
129
+
130
+ return {"function": "carry_nbt", "options": options}
131
+
132
+ def run(self, src: SrcData, state: StateData, dst: DstData) -> None:
133
+ dst.cacheable = False
134
+
135
+ src_nbt = src.nbt
136
+ if src_nbt is None:
137
+ return
138
+
139
+ full_nbt_path = state.nbt_path
140
+ if full_nbt_path is None:
141
+ # This only works within walk_input_nbt
142
+ return
143
+
144
+ tag = follow_nbt_path(src_nbt, full_nbt_path)
145
+ if tag is None:
146
+ # Could not find the tag
147
+ return
148
+
149
+ nbt_path = full_nbt_path[2]
150
+ path = nbt_path[:-1] if self._path is None else self._path
151
+ src_key, src_cls = nbt_path[-1]
152
+ key = src_key if self._key is None else self._key
153
+ tag_cls = src_cls if self._tag_cls is None else self._tag_cls
154
+
155
+ if not isinstance(tag, tag_cls):
156
+ assert isinstance(tag, AbstractBaseNumericTag) and issubclass(
157
+ tag_cls, AbstractBaseNumericTag
158
+ )
159
+ tag = tag_cls(tag)
160
+ dst.nbt.append((self._outer_name, self._outer_type, path, key, tag))
@@ -0,0 +1,80 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Self, Any
4
+ from collections.abc import Mapping, Iterable
5
+
6
+ from amulet.block import PropertyValueType, Block
7
+
8
+ from .abc import (
9
+ AbstractBaseTranslationFunction,
10
+ immutable_from_snbt,
11
+ Data,
12
+ )
13
+ from amulet.game.abc import JSONCompatible, JSONDict
14
+ from ._frozen import FrozenMapping, OrderedFrozenSet
15
+ from ._state import SrcData, StateData, DstData
16
+
17
+
18
+ class CarryProperties(AbstractBaseTranslationFunction):
19
+ # Class variables
20
+ Name = "carry_properties"
21
+ _instances = {}
22
+
23
+ # Instance variables
24
+ _properties: FrozenMapping[str, OrderedFrozenSet[PropertyValueType]]
25
+
26
+ def __init__(self, properties: Mapping[str, Iterable[PropertyValueType]]) -> None:
27
+ super().__init__()
28
+ assert isinstance(properties, Mapping)
29
+ frozen_properties = {}
30
+ for key, val in properties.items():
31
+ frozen_val = OrderedFrozenSet(val)
32
+ if not (
33
+ isinstance(key, str)
34
+ and all(isinstance(v, PropertyValueType) for v in frozen_val)
35
+ ):
36
+ raise TypeError
37
+ frozen_properties[key] = frozen_val
38
+ self._properties = FrozenMapping[str, OrderedFrozenSet[PropertyValueType]](
39
+ frozen_properties
40
+ )
41
+
42
+ def __reduce__(self) -> Any:
43
+ return CarryProperties, (self._properties,)
44
+
45
+ def _data(self) -> Data:
46
+ return self._properties
47
+
48
+ @classmethod
49
+ def from_json(cls, data: JSONCompatible) -> Self:
50
+ assert isinstance(data, dict)
51
+ assert data.get("function") == "carry_properties"
52
+ options = data["options"]
53
+ assert isinstance(options, dict)
54
+ properties = {}
55
+ for property_name, snbt_list in options.items():
56
+ assert isinstance(property_name, str)
57
+ assert isinstance(snbt_list, list)
58
+ values = []
59
+ for snbt in snbt_list:
60
+ assert isinstance(snbt, str)
61
+ values.append(immutable_from_snbt(snbt))
62
+ properties[property_name] = values
63
+ return cls(properties)
64
+
65
+ def to_json(self) -> JSONDict:
66
+ return {
67
+ "function": "carry_properties",
68
+ "options": {
69
+ key: [v.to_snbt() for v in val] for key, val in self._properties.items()
70
+ },
71
+ }
72
+
73
+ def run(self, src: SrcData, state: StateData, dst: DstData) -> None:
74
+ block = src.block
75
+ assert isinstance(block, Block)
76
+ src_properties = block.properties
77
+ for key, options in self._properties.items():
78
+ val = src_properties.get(key)
79
+ if val is not None and val in options:
80
+ dst.properties[key] = val
@@ -0,0 +1,143 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Self, Any, TypeVar, Callable
4
+ from collections.abc import Sequence
5
+
6
+ from .abc import AbstractBaseTranslationFunction, Data
7
+ from amulet.game.abc import JSONCompatible, JSONDict
8
+ from ._state import SrcData, StateData, DstData
9
+
10
+ from ._code_functions.banner_pattern import (
11
+ to_universal as banner_pattern_2u,
12
+ from_universal as banner_pattern_fu,
13
+ )
14
+ from ._code_functions.bedrock_chest_connection import (
15
+ bedrock_chest_connection_self,
16
+ bedrock_chest_connection_self_120,
17
+ bedrock_chest_connection_other_left,
18
+ bedrock_chest_connection_other_left_120,
19
+ bedrock_chest_connection_other_right,
20
+ bedrock_chest_connection_other_right_120,
21
+ from_universal as bedrock_chest_fu,
22
+ )
23
+ from ._code_functions.custom_name import (
24
+ bedrock_extended_to_universal as bedrock_custom_name_2u,
25
+ bedrock_extended_from_universal as bedrock_custom_name_fu,
26
+ )
27
+ from ._code_functions.bedrock_moving_block_pos import (
28
+ to_universal as bedrock_moving_block_pos_2u,
29
+ from_universal as bedrock_moving_block_pos_fu,
30
+ )
31
+ from ._code_functions.bedrock_sign import (
32
+ to_universal as bedrock_sign_2u,
33
+ from_universal as bedrock_sign_fu,
34
+ to_universal_120 as bedrock_sign_2u_120,
35
+ from_universal_120 as bedrock_sign_fu_120,
36
+ )
37
+ from ._code_functions.bedrock_skull_rotation import (
38
+ to_universal as bedrock_skull_rotation_2u,
39
+ )
40
+
41
+
42
+ T = TypeVar("T")
43
+
44
+
45
+ def check_list(l: list[Any], t: type[T]) -> list[T]:
46
+ assert all(isinstance(el, t) for el in l)
47
+ return l
48
+
49
+
50
+ FunctionLUT: dict[str, Callable[[SrcData, StateData, DstData], None]] = {
51
+ "banner_pattern_2u": banner_pattern_2u,
52
+ "banner_pattern_fu": banner_pattern_fu,
53
+ "bedrock_chest_connection_other_left": bedrock_chest_connection_other_left,
54
+ "bedrock_chest_connection_other_left_120": bedrock_chest_connection_other_left_120,
55
+ "bedrock_chest_connection_other_right": bedrock_chest_connection_other_right,
56
+ "bedrock_chest_connection_other_right_120": bedrock_chest_connection_other_right_120,
57
+ "bedrock_chest_connection_self": bedrock_chest_connection_self,
58
+ "bedrock_chest_connection_self_120": bedrock_chest_connection_self_120,
59
+ "bedrock_chest_fu": bedrock_chest_fu,
60
+ "bedrock_cmd_custom_name_2u": bedrock_custom_name_2u,
61
+ "bedrock_cmd_custom_name_fu": bedrock_custom_name_fu,
62
+ "bedrock_moving_block_pos_2u": bedrock_moving_block_pos_2u,
63
+ "bedrock_moving_block_pos_fu": bedrock_moving_block_pos_fu,
64
+ "bedrock_sign_2u": bedrock_sign_2u,
65
+ "bedrock_sign_2u_120": bedrock_sign_2u_120,
66
+ "bedrock_sign_fu": bedrock_sign_fu,
67
+ "bedrock_sign_fu_120": bedrock_sign_fu_120,
68
+ "bedrock_skull_rotation_2u": bedrock_skull_rotation_2u,
69
+ }
70
+
71
+
72
+ class Code(AbstractBaseTranslationFunction):
73
+ # Class variables
74
+ Name = "code"
75
+ _instances = {}
76
+
77
+ # Instance variables
78
+ _inputs: tuple[str, ...]
79
+ _outputs: tuple[str, ...]
80
+ _function_name: str
81
+
82
+ def __init__(
83
+ self,
84
+ inputs: Sequence[str],
85
+ outputs: Sequence[str],
86
+ function_name: str,
87
+ ) -> None:
88
+ super().__init__()
89
+ self._inputs = tuple(inputs)
90
+ assert all(
91
+ el
92
+ in {
93
+ "namespace",
94
+ "base_name",
95
+ "properties",
96
+ "nbt",
97
+ "location",
98
+ }
99
+ for el in self._inputs
100
+ )
101
+ self._outputs = tuple(outputs)
102
+ assert all(
103
+ el in {"output_name", "output_type", "new_properties", "new_nbt"}
104
+ for el in self._outputs
105
+ )
106
+ self._function_name = function_name
107
+
108
+ def __reduce__(self) -> Any:
109
+ return Code, (self._inputs, self._outputs, self._function_name)
110
+
111
+ def _data(self) -> Data:
112
+ return self._inputs, self._outputs, self._function_name
113
+
114
+ @classmethod
115
+ def from_json(cls, data: JSONCompatible) -> Self:
116
+ assert isinstance(data, dict)
117
+ assert data.get("function") == "code"
118
+ options = data["options"]
119
+ assert isinstance(options, dict)
120
+ raw_inputs = options["input"]
121
+ assert isinstance(raw_inputs, list)
122
+ inputs = check_list(raw_inputs, str)
123
+ raw_outputs = options["output"]
124
+ assert isinstance(raw_outputs, list)
125
+ outputs = check_list(raw_outputs, str)
126
+ function = options["function"]
127
+ assert isinstance(function, str)
128
+ assert function in FunctionLUT, function
129
+ return cls(inputs, outputs, function)
130
+
131
+ def to_json(self) -> JSONDict:
132
+ return {
133
+ "function": "code",
134
+ "options": {
135
+ "input": list(self._inputs),
136
+ "output": list(self._outputs),
137
+ "function": self._function_name,
138
+ },
139
+ }
140
+
141
+ def run(self, src: SrcData, state: StateData, dst: DstData) -> None:
142
+ dst.cacheable = False
143
+ FunctionLUT[self._function_name](src, state, dst)
@@ -0,0 +1,66 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Self, Any
4
+ from collections.abc import Mapping
5
+
6
+ from amulet.block import Block
7
+ from .abc import (
8
+ AbstractBaseTranslationFunction,
9
+ translation_function_from_json,
10
+ Data,
11
+ )
12
+ from amulet.game.abc import JSONCompatible, JSONDict
13
+ from ._frozen import FrozenMapping
14
+ from ._state import SrcData, StateData, DstData
15
+
16
+
17
+ class MapBlockName(AbstractBaseTranslationFunction):
18
+ # Class variables
19
+ Name = "map_block_name"
20
+ _instances = {}
21
+
22
+ # Instance variables
23
+ _blocks: FrozenMapping[tuple[str, str], AbstractBaseTranslationFunction]
24
+
25
+ def __init__(
26
+ self, blocks: Mapping[tuple[str, str], AbstractBaseTranslationFunction]
27
+ ) -> None:
28
+ super().__init__()
29
+ self._blocks = FrozenMapping[tuple[str, str], AbstractBaseTranslationFunction](
30
+ blocks
31
+ )
32
+
33
+ def __reduce__(self) -> Any:
34
+ return MapBlockName, (self._blocks,)
35
+
36
+ def _data(self) -> Data:
37
+ return self._blocks
38
+
39
+ @classmethod
40
+ def from_json(cls, data: JSONCompatible) -> Self:
41
+ assert isinstance(data, dict)
42
+ assert data.get("function") == "map_block_name"
43
+ blocks = {}
44
+ options = data["options"]
45
+ assert isinstance(options, dict)
46
+ for block_name, function in options.items():
47
+ assert isinstance(block_name, str)
48
+ namespace, base_name = block_name.split(":", 1)
49
+ blocks[(namespace, base_name)] = translation_function_from_json(function)
50
+ return cls(blocks)
51
+
52
+ def to_json(self) -> JSONDict:
53
+ return {
54
+ "function": "map_block_name",
55
+ "options": {
56
+ ":".join(block_name): func.to_json()
57
+ for block_name, func in self._blocks.items()
58
+ },
59
+ }
60
+
61
+ def run(self, src: SrcData, state: StateData, dst: DstData) -> None:
62
+ block = src.block
63
+ assert isinstance(block, Block)
64
+ func = self._blocks.get((block.namespace, block.base_name))
65
+ if func is not None:
66
+ func.run(src, state, dst)