amulet-core 2.0a5__cp311-cp311-macosx_10_9_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-311-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,152 @@
1
+ from typing import Callable, Any
2
+ from amulet_nbt import CompoundTag, IntTag, ByteTag, StringTag, AbstractBaseTag
3
+ from .._state import SrcData, StateData, DstData
4
+
5
+
6
+ def _bedrock_chest_connection(
7
+ facing_property: str, connections: dict[tuple[Any, int, int], StringTag]
8
+ ) -> Callable[[SrcData, StateData, DstData], None]:
9
+ def main(src: SrcData, state: StateData, dst: DstData) -> None:
10
+ nbt = src.nbt
11
+ if nbt is None:
12
+ return
13
+
14
+ tag = nbt.tag
15
+ if not isinstance(tag, CompoundTag):
16
+ return
17
+
18
+ if tag.get("pairlead") != ByteTag(1):
19
+ return
20
+
21
+ pairx = tag.get("pairx")
22
+ if not isinstance(pairx, IntTag):
23
+ return
24
+
25
+ pairz = tag.get("pairz")
26
+ if not isinstance(pairz, IntTag):
27
+ return
28
+
29
+ block = src.block
30
+ if block is None:
31
+ return
32
+ extra = src.extra
33
+ if extra is None:
34
+ dst.extra_needed = True
35
+ return
36
+
37
+ facing_direction = block.properties.get(facing_property)
38
+ if not isinstance(facing_direction, AbstractBaseTag):
39
+ return
40
+
41
+ dx = pairx.py_int - extra.absolute_coordinates[0]
42
+ dz = pairz.py_int - extra.absolute_coordinates[2]
43
+
44
+ connection = connections.get((facing_direction.py_data, dx, dz))
45
+ if connection is None:
46
+ return
47
+ dst.properties["connection"] = connection
48
+
49
+ return main
50
+
51
+
52
+ bedrock_chest_connection_other_left = _bedrock_chest_connection(
53
+ "facing_direction",
54
+ {
55
+ (2, -1, 0): StringTag("left"), # north
56
+ (3, 1, 0): StringTag("left"), # south
57
+ (4, 0, 1): StringTag("left"), # west
58
+ (5, 0, -1): StringTag("left"), # east
59
+ },
60
+ )
61
+
62
+ bedrock_chest_connection_other_right = _bedrock_chest_connection(
63
+ "facing_direction",
64
+ {
65
+ (2, 1, 0): StringTag("right"), # north
66
+ (3, -1, 0): StringTag("right"), # south
67
+ (4, 0, -1): StringTag("right"), # west
68
+ (5, 0, 1): StringTag("right"), # east
69
+ },
70
+ )
71
+
72
+ bedrock_chest_connection_self = _bedrock_chest_connection(
73
+ "facing_direction",
74
+ {
75
+ (2, -1, 0): StringTag("right"), # north
76
+ (2, 1, 0): StringTag("left"), # north
77
+ (3, 1, 0): StringTag("right"), # south
78
+ (3, -1, 0): StringTag("left"), # south
79
+ (4, 0, 1): StringTag("right"), # west
80
+ (4, 0, -1): StringTag("left"), # west
81
+ (5, 0, -1): StringTag("right"), # east
82
+ (5, 0, 1): StringTag("left"), # east
83
+ },
84
+ )
85
+
86
+ bedrock_chest_connection_other_left_120 = _bedrock_chest_connection(
87
+ "minecraft:cardinal_direction",
88
+ {
89
+ ("north", -1, 0): StringTag("left"), # north
90
+ ("south", 1, 0): StringTag("left"), # south
91
+ ("west", 0, 1): StringTag("left"), # west
92
+ ("east", 0, -1): StringTag("left"), # east
93
+ },
94
+ )
95
+
96
+ bedrock_chest_connection_other_right_120 = _bedrock_chest_connection(
97
+ "minecraft:cardinal_direction",
98
+ {
99
+ ("north", 1, 0): StringTag("right"), # north
100
+ ("south", -1, 0): StringTag("right"), # south
101
+ ("west", 0, -1): StringTag("right"), # west
102
+ ("east", 0, 1): StringTag("right"), # east
103
+ },
104
+ )
105
+
106
+ bedrock_chest_connection_self_120 = _bedrock_chest_connection(
107
+ "minecraft:cardinal_direction",
108
+ {
109
+ ("north", -1, 0): StringTag("right"), # north
110
+ ("north", 1, 0): StringTag("left"), # north
111
+ ("south", 1, 0): StringTag("right"), # south
112
+ ("south", -1, 0): StringTag("left"), # south
113
+ ("west", 0, 1): StringTag("right"), # west
114
+ ("west", 0, -1): StringTag("left"), # west
115
+ ("east", 0, -1): StringTag("right"), # east
116
+ ("east", 0, 1): StringTag("left"), # east
117
+ },
118
+ )
119
+
120
+
121
+ def from_universal(src: SrcData, state: StateData, dst: DstData) -> None:
122
+ block = src.block
123
+ if block is None:
124
+ return
125
+
126
+ extra = src.extra
127
+ if extra is None:
128
+ dst.extra_needed = True
129
+ return
130
+
131
+ facing = block.properties.get("facing")
132
+ if not isinstance(facing, StringTag):
133
+ return
134
+
135
+ x, _, z = extra.absolute_coordinates
136
+ facing_str = facing.py_str
137
+ if facing_str == "north":
138
+ dst.nbt.append(("", CompoundTag, (), "pairlead", ByteTag(1)))
139
+ dst.nbt.append(("", CompoundTag, (), "pairx", IntTag(x - 1)))
140
+ dst.nbt.append(("", CompoundTag, (), "pairz", IntTag(z)))
141
+ elif facing_str == "south":
142
+ dst.nbt.append(("", CompoundTag, (), "pairlead", ByteTag(1)))
143
+ dst.nbt.append(("", CompoundTag, (), "pairx", IntTag(x + 1)))
144
+ dst.nbt.append(("", CompoundTag, (), "pairz", IntTag(z)))
145
+ elif facing_str == "west":
146
+ dst.nbt.append(("", CompoundTag, (), "pairlead", ByteTag(1)))
147
+ dst.nbt.append(("", CompoundTag, (), "pairx", IntTag(x)))
148
+ dst.nbt.append(("", CompoundTag, (), "pairz", IntTag(z + 1)))
149
+ elif facing_str == "east":
150
+ dst.nbt.append(("", CompoundTag, (), "pairlead", ByteTag(1)))
151
+ dst.nbt.append(("", CompoundTag, (), "pairx", IntTag(x)))
152
+ dst.nbt.append(("", CompoundTag, (), "pairz", IntTag(z - 1)))
@@ -0,0 +1,88 @@
1
+ from amulet_nbt import CompoundTag, IntTag
2
+ from .._state import SrcData, StateData, DstData
3
+
4
+
5
+ def to_universal(src: SrcData, state: StateData, dst: DstData) -> None:
6
+ if src.extra is None:
7
+ return
8
+
9
+ x, y, z = src.extra.absolute_coordinates
10
+
11
+ nbt = src.nbt
12
+ if nbt is None:
13
+ return
14
+
15
+ tag = nbt.tag
16
+ if not isinstance(tag, CompoundTag):
17
+ return
18
+
19
+ pistonPosX = tag.get("pistonPosX")
20
+ if not isinstance(pistonPosX, IntTag):
21
+ return
22
+ pistonPosY = tag.get("pistonPosY")
23
+ if not isinstance(pistonPosY, IntTag):
24
+ return
25
+ pistonPosZ = tag.get("pistonPosZ")
26
+ if not isinstance(pistonPosZ, IntTag):
27
+ return
28
+
29
+ dst.nbt.append(
30
+ (
31
+ "",
32
+ CompoundTag,
33
+ (("utags", CompoundTag),),
34
+ "pistonPosdX",
35
+ IntTag(pistonPosX.py_int - x),
36
+ )
37
+ )
38
+ dst.nbt.append(
39
+ (
40
+ "",
41
+ CompoundTag,
42
+ (("utags", CompoundTag),),
43
+ "pistonPosdY",
44
+ IntTag(pistonPosY.py_int - y),
45
+ )
46
+ )
47
+ dst.nbt.append(
48
+ (
49
+ "",
50
+ CompoundTag,
51
+ (("utags", CompoundTag),),
52
+ "pistonPosdZ",
53
+ IntTag(pistonPosZ.py_int - z),
54
+ )
55
+ )
56
+
57
+
58
+ def from_universal(src: SrcData, state: StateData, dst: DstData) -> None:
59
+ if src.extra is None:
60
+ return
61
+
62
+ x, y, z = src.extra.absolute_coordinates
63
+
64
+ nbt = src.nbt
65
+ if nbt is None:
66
+ return
67
+
68
+ tag = nbt.tag
69
+ if not isinstance(tag, CompoundTag):
70
+ return
71
+
72
+ utags = tag.get("utags")
73
+ if not isinstance(utags, CompoundTag):
74
+ return
75
+
76
+ pistonPosdX = utags.get("pistonPosdX")
77
+ if not isinstance(pistonPosdX, IntTag):
78
+ return
79
+ pistonPosdY = utags.get("pistonPosdY")
80
+ if not isinstance(pistonPosdY, IntTag):
81
+ return
82
+ pistonPosdZ = utags.get("pistonPosdZ")
83
+ if not isinstance(pistonPosdZ, IntTag):
84
+ return
85
+
86
+ dst.nbt.append(("", CompoundTag, (), "pistonPosX", IntTag(pistonPosdX.py_int + x)))
87
+ dst.nbt.append(("", CompoundTag, (), "pistonPosY", IntTag(pistonPosdY.py_int + y)))
88
+ dst.nbt.append(("", CompoundTag, (), "pistonPosZ", IntTag(pistonPosdZ.py_int + z)))
@@ -0,0 +1,152 @@
1
+ import json
2
+ from typing import Any
3
+ from uuid import uuid4
4
+
5
+ from amulet_nbt import StringTag, CompoundTag, ListTag
6
+ from ._text import RawTextComponent, ExtendedBedrockSectionParser
7
+ from .._state import SrcData, StateData, DstData
8
+
9
+
10
+ BedrockFrontText = str(uuid4())
11
+ BedrockBackText = str(uuid4())
12
+
13
+
14
+ def _to_universal(
15
+ src: CompoundTag,
16
+ src_key: str,
17
+ dst: DstData,
18
+ universal_native_key: str,
19
+ universal_key: str,
20
+ ) -> None:
21
+ text = src.get_string(src_key)
22
+ if not isinstance(text, StringTag):
23
+ return
24
+
25
+ dst.nbt.append(
26
+ (
27
+ "",
28
+ CompoundTag,
29
+ (("utags", CompoundTag),),
30
+ universal_native_key,
31
+ text,
32
+ )
33
+ )
34
+
35
+ if text:
36
+ for line_num, component in enumerate(
37
+ RawTextComponent.from_section_text(
38
+ text.py_str, ExtendedBedrockSectionParser, True
39
+ )
40
+ ):
41
+ dst.nbt.append(
42
+ (
43
+ "",
44
+ CompoundTag,
45
+ (
46
+ ("utags", CompoundTag),
47
+ (universal_key, CompoundTag),
48
+ ("messages", ListTag),
49
+ ),
50
+ line_num,
51
+ StringTag(json.dumps(component.to_java_raw_text())),
52
+ )
53
+ )
54
+
55
+
56
+ def _from_universal(
57
+ utags: CompoundTag,
58
+ universal_native_key: str,
59
+ universal_key: str,
60
+ dst: DstData,
61
+ native_key: str,
62
+ ) -> None:
63
+ native_text = utags.get_string(universal_native_key)
64
+ text: StringTag
65
+ if isinstance(native_text, StringTag):
66
+ text = native_text
67
+ else:
68
+ messages = utags.get_compound(universal_key, CompoundTag()).get_list(
69
+ "messages", ListTag()
70
+ )
71
+
72
+ lines: list[Any] = [""]
73
+ if messages.element_class is StringTag:
74
+ for line_num in range(4):
75
+ if line_num >= len(messages):
76
+ lines.append("")
77
+ else:
78
+ try:
79
+ lines.append(json.loads(messages.get_string(line_num).py_str))
80
+ except:
81
+ lines.append("")
82
+ else:
83
+ lines.extend([""] * 4)
84
+
85
+ text = StringTag(
86
+ RawTextComponent.from_java_raw_text(lines).to_section_text(
87
+ ExtendedBedrockSectionParser
88
+ )
89
+ )
90
+
91
+ dst.nbt.append(
92
+ (
93
+ "",
94
+ CompoundTag,
95
+ (),
96
+ native_key,
97
+ text,
98
+ )
99
+ )
100
+
101
+
102
+ def to_universal(src: SrcData, state: StateData, dst: DstData) -> None:
103
+ nbt = src.nbt
104
+ if nbt is None:
105
+ return
106
+
107
+ tag = nbt.tag
108
+ if not isinstance(tag, CompoundTag):
109
+ return
110
+
111
+ _to_universal(tag, "Text", dst, BedrockFrontText, "front_text")
112
+
113
+
114
+ def from_universal(src: SrcData, state: StateData, dst: DstData) -> None:
115
+ nbt = src.nbt
116
+ if nbt is not None:
117
+ tag = nbt.tag
118
+ if isinstance(tag, CompoundTag):
119
+ utags = tag.get_compound("utags")
120
+ if isinstance(utags, CompoundTag):
121
+ _from_universal(utags, BedrockFrontText, "front_text", dst, "Text")
122
+ return
123
+
124
+ dst.nbt.append(("", CompoundTag, (), "Text", StringTag()))
125
+
126
+
127
+ def to_universal_120(src: SrcData, state: StateData, dst: DstData) -> None:
128
+ nbt = src.nbt
129
+ if nbt is None:
130
+ return
131
+
132
+ tag = nbt.tag
133
+ if not isinstance(tag, CompoundTag):
134
+ return
135
+
136
+ _to_universal(tag, "FrontText", dst, BedrockFrontText, "front_text")
137
+ _to_universal(tag, "BackText", dst, BedrockBackText, "back_text")
138
+
139
+
140
+ def from_universal_120(src: SrcData, state: StateData, dst: DstData) -> None:
141
+ nbt = src.nbt
142
+ if nbt is not None:
143
+ tag = nbt.tag
144
+ if isinstance(tag, CompoundTag):
145
+ utags = tag.get_compound("utags")
146
+ if isinstance(utags, CompoundTag):
147
+ _from_universal(utags, BedrockFrontText, "front_text", dst, "FrontText")
148
+ _from_universal(utags, BedrockBackText, "back_text", dst, "BackText")
149
+ return
150
+
151
+ dst.nbt.append(("", CompoundTag, (), "FrontText", StringTag()))
152
+ dst.nbt.append(("", CompoundTag, (), "BackText", StringTag()))
@@ -0,0 +1,16 @@
1
+ from amulet_nbt import CompoundTag, FloatTag, StringTag
2
+ from .._state import SrcData, StateData, DstData
3
+
4
+
5
+ def to_universal(src: SrcData, state: StateData, dst: DstData) -> None:
6
+ nbt = src.nbt
7
+ if nbt is not None:
8
+ tag = nbt.tag
9
+ if isinstance(tag, CompoundTag):
10
+ rotation = tag.get("Rotation")
11
+ if isinstance(rotation, FloatTag):
12
+ dst.properties["rotation"] = StringTag(
13
+ f"{int(rotation.py_float // 22.5) % 16}"
14
+ )
15
+ return
16
+ dst.properties["rotation"] = StringTag("0")
@@ -0,0 +1,146 @@
1
+ from uuid import uuid4
2
+ import json
3
+ from typing import Callable
4
+
5
+ from amulet_nbt import CompoundTag, StringTag
6
+
7
+ from .._state import SrcData, StateData, DstData
8
+ from ._text import (
9
+ RawTextComponent,
10
+ BedrockSectionParser,
11
+ ExtendedBedrockSectionParser,
12
+ JavaSectionParser,
13
+ )
14
+
15
+
16
+ JavaSectionText = str(uuid4())
17
+ JavaRawText = str(uuid4())
18
+ BedrockSectionText = str(uuid4())
19
+ BedrockExtendedSectionText = str(uuid4())
20
+
21
+
22
+ def get_custom_name(src: SrcData, dst: DstData, key: str) -> None:
23
+ nbt = src.nbt
24
+ if nbt is None:
25
+ return
26
+
27
+ tag = nbt.tag
28
+ if not isinstance(tag, CompoundTag):
29
+ return
30
+
31
+ custom_name = tag.get("CustomName")
32
+ if not isinstance(custom_name, StringTag):
33
+ return
34
+
35
+ # Store the raw value so we can non-destructively recover it
36
+ dst.nbt.append(("", CompoundTag, (("utags", CompoundTag),), key, custom_name))
37
+
38
+
39
+ def java_section_to_universal(src: SrcData, state: StateData, dst: DstData) -> None:
40
+ get_custom_name(src, dst, JavaSectionText)
41
+
42
+
43
+ def java_raw_to_universal(src: SrcData, state: StateData, dst: DstData) -> None:
44
+ get_custom_name(src, dst, JavaRawText)
45
+
46
+
47
+ def bedrock_to_universal(src: SrcData, state: StateData, dst: DstData) -> None:
48
+ get_custom_name(src, dst, BedrockSectionText)
49
+
50
+
51
+ def bedrock_extended_to_universal(src: SrcData, state: StateData, dst: DstData) -> None:
52
+ get_custom_name(src, dst, BedrockExtendedSectionText)
53
+
54
+
55
+ def set_custom_name(
56
+ src: SrcData,
57
+ dst: DstData,
58
+ target: str,
59
+ component_to_raw: Callable[[RawTextComponent], StringTag],
60
+ ) -> None:
61
+ nbt = src.nbt
62
+ if nbt is None:
63
+ return
64
+
65
+ tag = nbt.tag
66
+ if not isinstance(tag, CompoundTag):
67
+ return
68
+
69
+ utags = tag.get("utags")
70
+ if not isinstance(utags, CompoundTag):
71
+ return
72
+
73
+ if isinstance((native_custom_name := utags.get(target)), StringTag):
74
+ custom_name = native_custom_name
75
+ elif isinstance(
76
+ (java_section_custom_name := utags.get(JavaSectionText)), StringTag
77
+ ):
78
+ component = RawTextComponent.from_section_text(
79
+ java_section_custom_name.py_str, JavaSectionParser
80
+ )
81
+ custom_name = component_to_raw(component)
82
+ elif isinstance((java_raw_custom_name := utags.get(JavaRawText)), StringTag):
83
+ try:
84
+ component = RawTextComponent.from_java_raw_text(
85
+ json.loads(java_raw_custom_name.py_str)
86
+ )
87
+ except:
88
+ custom_name = StringTag()
89
+ else:
90
+ custom_name = component_to_raw(component)
91
+
92
+ elif isinstance((bedrock_custom_name := utags.get(BedrockSectionText)), StringTag):
93
+ component = RawTextComponent.from_section_text(
94
+ bedrock_custom_name.py_str, BedrockSectionParser
95
+ )
96
+ custom_name = component_to_raw(component)
97
+ elif isinstance(
98
+ (bedrock_extended_custom_name := utags.get(BedrockExtendedSectionText)),
99
+ StringTag,
100
+ ):
101
+ component = RawTextComponent.from_section_text(
102
+ bedrock_extended_custom_name.py_str, ExtendedBedrockSectionParser
103
+ )
104
+ custom_name = component_to_raw(component)
105
+ else:
106
+ custom_name = StringTag()
107
+
108
+ dst.nbt.append(
109
+ (
110
+ "",
111
+ CompoundTag,
112
+ (),
113
+ "CustomName",
114
+ custom_name,
115
+ )
116
+ )
117
+
118
+
119
+ def java_section_from_universal(src: SrcData, state: StateData, dst: DstData) -> None:
120
+ def component_to_raw(component: RawTextComponent) -> StringTag:
121
+ return StringTag(component.to_section_text(JavaSectionParser))
122
+
123
+ set_custom_name(src, dst, JavaSectionText, component_to_raw)
124
+
125
+
126
+ def java_raw_from_universal(src: SrcData, state: StateData, dst: DstData) -> None:
127
+ def component_to_raw(component: RawTextComponent) -> StringTag:
128
+ return StringTag(json.dumps(component.to_java_raw_text()))
129
+
130
+ set_custom_name(src, dst, JavaSectionText, component_to_raw)
131
+
132
+
133
+ def bedrock_from_universal(src: SrcData, state: StateData, dst: DstData) -> None:
134
+ def component_to_raw(component: RawTextComponent) -> StringTag:
135
+ return StringTag(component.to_section_text(BedrockSectionParser))
136
+
137
+ set_custom_name(src, dst, BedrockSectionText, component_to_raw)
138
+
139
+
140
+ def bedrock_extended_from_universal(
141
+ src: SrcData, state: StateData, dst: DstData
142
+ ) -> None:
143
+ def component_to_raw(component: RawTextComponent) -> StringTag:
144
+ return StringTag(component.to_section_text(ExtendedBedrockSectionParser))
145
+
146
+ set_custom_name(src, dst, BedrockExtendedSectionText, component_to_raw)
@@ -0,0 +1,66 @@
1
+ from typing import TypeVar, Any
2
+ from collections.abc import Mapping, Iterator, Hashable, Set, Iterable
3
+
4
+ K = TypeVar("K", bound=Hashable)
5
+ V = TypeVar("V", bound=Hashable)
6
+
7
+
8
+ class FrozenMapping(Mapping[K, V], Hashable):
9
+ """
10
+ A hashable Mapping class.
11
+ All values in the mapping must be hashable.
12
+ """
13
+
14
+ _map: Mapping[K, V]
15
+ _h: int | None
16
+
17
+ def __init__(self, mapping: Mapping) -> None:
18
+ self._map: dict[K, V] = dict(mapping)
19
+ self._h = None
20
+
21
+ def __getitem__(self, k: K) -> V:
22
+ return self._map[k]
23
+
24
+ def __len__(self) -> int:
25
+ return len(self._map)
26
+
27
+ def __iter__(self) -> Iterator[K]:
28
+ return iter(self._map)
29
+
30
+ def __hash__(self) -> int:
31
+ if self._h is None:
32
+ self._h = hash(frozenset(self._map.items()))
33
+ return self._h
34
+
35
+ def __eq__(self, other: Any) -> bool:
36
+ if not isinstance(other, Mapping):
37
+ return NotImplemented
38
+ return self._map == other
39
+
40
+
41
+ class OrderedFrozenSet(Set[K], Hashable):
42
+ _map: dict[K, None]
43
+ _h: int | None
44
+
45
+ def __init__(self, items: Iterable[K]) -> None:
46
+ self._map = dict.fromkeys(items)
47
+ self._h = None
48
+
49
+ def __contains__(self, item: Any) -> bool:
50
+ return item in self._map
51
+
52
+ def __len__(self) -> int:
53
+ return len(self._map)
54
+
55
+ def __iter__(self) -> Iterator[K]:
56
+ yield from self._map
57
+
58
+ def __hash__(self) -> int:
59
+ if self._h is None:
60
+ self._h = hash(tuple(self._map))
61
+ return self._h
62
+
63
+ def __eq__(self, other: Any) -> bool:
64
+ if not isinstance(other, Set):
65
+ return NotImplemented
66
+ return self._map.keys() == other
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Union, Callable
4
+ from dataclasses import dataclass, field
5
+
6
+ from amulet_nbt import (
7
+ NamedTag,
8
+ ListTag,
9
+ CompoundTag,
10
+ )
11
+
12
+ from amulet.block import Block, PropertyValueType
13
+ from amulet.block_entity import BlockEntity
14
+ from amulet.entity import Entity
15
+ from amulet.data_types import BlockCoordinates
16
+ from ._typing import NBTTagT, NBTPath
17
+
18
+
19
+ @dataclass(frozen=True)
20
+ class SrcDataExtra:
21
+ absolute_coordinates: BlockCoordinates
22
+ get_block_callback: Callable[[BlockCoordinates], tuple[Block, BlockEntity | None]]
23
+
24
+
25
+ @dataclass(frozen=True)
26
+ class SrcData:
27
+ block: Block | None
28
+ nbt: NamedTag | None
29
+ extra: SrcDataExtra | None
30
+
31
+
32
+ @dataclass
33
+ class StateData:
34
+ relative_location: BlockCoordinates = (0, 0, 0)
35
+ # nbt_path is only set when within walk_input_nbt
36
+ nbt_path: tuple[str, type[ListTag] | type[CompoundTag], NBTPath] | None = None
37
+
38
+
39
+ @dataclass
40
+ class DstData:
41
+ cls: type[Block] | type[Entity] | None = None
42
+ resource_id: tuple[str, str] | None = None
43
+ properties: dict[str, PropertyValueType] = field(default_factory=dict)
44
+ nbt: list[
45
+ tuple[
46
+ str,
47
+ type[ListTag] | type[CompoundTag],
48
+ NBTPath,
49
+ Union[str, int],
50
+ NBTTagT,
51
+ ]
52
+ ] = field(default_factory=list)
53
+ extra_needed: bool = False
54
+ cacheable: bool = True