amulet-core 1.9.19__py3-none-any.whl → 1.9.20__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.

Potentially problematic release.


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

Files changed (198) hide show
  1. amulet/__init__.py +27 -27
  2. amulet/__pyinstaller/__init__.py +2 -2
  3. amulet/__pyinstaller/hook-amulet.py +4 -4
  4. amulet/_version.py +21 -21
  5. amulet/api/__init__.py +2 -2
  6. amulet/api/abstract_base_entity.py +128 -128
  7. amulet/api/block.py +630 -630
  8. amulet/api/block_entity.py +71 -71
  9. amulet/api/cache.py +107 -107
  10. amulet/api/chunk/__init__.py +6 -6
  11. amulet/api/chunk/biomes.py +207 -207
  12. amulet/api/chunk/block_entity_dict.py +175 -175
  13. amulet/api/chunk/blocks.py +46 -46
  14. amulet/api/chunk/chunk.py +389 -389
  15. amulet/api/chunk/entity_list.py +75 -75
  16. amulet/api/chunk/status.py +167 -167
  17. amulet/api/data_types/__init__.py +4 -4
  18. amulet/api/data_types/generic_types.py +4 -4
  19. amulet/api/data_types/operation_types.py +16 -16
  20. amulet/api/data_types/world_types.py +49 -49
  21. amulet/api/data_types/wrapper_types.py +71 -71
  22. amulet/api/entity.py +74 -74
  23. amulet/api/errors.py +119 -119
  24. amulet/api/history/__init__.py +36 -36
  25. amulet/api/history/base/__init__.py +3 -3
  26. amulet/api/history/base/base_history.py +26 -26
  27. amulet/api/history/base/history_manager.py +63 -63
  28. amulet/api/history/base/revision_manager.py +73 -73
  29. amulet/api/history/changeable.py +15 -15
  30. amulet/api/history/data_types.py +7 -7
  31. amulet/api/history/history_manager/__init__.py +3 -3
  32. amulet/api/history/history_manager/container.py +102 -102
  33. amulet/api/history/history_manager/database.py +279 -279
  34. amulet/api/history/history_manager/meta.py +93 -93
  35. amulet/api/history/history_manager/object.py +116 -116
  36. amulet/api/history/revision_manager/__init__.py +2 -2
  37. amulet/api/history/revision_manager/disk.py +33 -33
  38. amulet/api/history/revision_manager/ram.py +12 -12
  39. amulet/api/item.py +75 -75
  40. amulet/api/level/__init__.py +4 -4
  41. amulet/api/level/base_level/__init__.py +1 -1
  42. amulet/api/level/base_level/base_level.py +1035 -1026
  43. amulet/api/level/base_level/chunk_manager.py +227 -227
  44. amulet/api/level/base_level/clone.py +389 -389
  45. amulet/api/level/base_level/player_manager.py +101 -101
  46. amulet/api/level/immutable_structure/__init__.py +1 -1
  47. amulet/api/level/immutable_structure/immutable_structure.py +94 -94
  48. amulet/api/level/immutable_structure/void_format_wrapper.py +117 -117
  49. amulet/api/level/structure.py +22 -22
  50. amulet/api/level/world.py +19 -19
  51. amulet/api/partial_3d_array/__init__.py +2 -2
  52. amulet/api/partial_3d_array/base_partial_3d_array.py +263 -263
  53. amulet/api/partial_3d_array/bounded_partial_3d_array.py +528 -528
  54. amulet/api/partial_3d_array/data_types.py +15 -15
  55. amulet/api/partial_3d_array/unbounded_partial_3d_array.py +229 -229
  56. amulet/api/partial_3d_array/util.py +152 -152
  57. amulet/api/player.py +65 -65
  58. amulet/api/registry/__init__.py +2 -2
  59. amulet/api/registry/base_registry.py +34 -34
  60. amulet/api/registry/biome_manager.py +153 -153
  61. amulet/api/registry/block_manager.py +156 -156
  62. amulet/api/selection/__init__.py +2 -2
  63. amulet/api/selection/abstract_selection.py +315 -315
  64. amulet/api/selection/box.py +805 -805
  65. amulet/api/selection/group.py +488 -488
  66. amulet/api/structure.py +37 -37
  67. amulet/api/wrapper/__init__.py +8 -8
  68. amulet/api/wrapper/chunk/interface.py +441 -441
  69. amulet/api/wrapper/chunk/translator.py +567 -567
  70. amulet/api/wrapper/format_wrapper.py +772 -772
  71. amulet/api/wrapper/structure_format_wrapper.py +116 -116
  72. amulet/api/wrapper/world_format_wrapper.py +63 -63
  73. amulet/level/__init__.py +1 -1
  74. amulet/level/formats/anvil_forge_world.py +40 -40
  75. amulet/level/formats/anvil_world/__init__.py +3 -3
  76. amulet/level/formats/anvil_world/_sector_manager.py +291 -384
  77. amulet/level/formats/anvil_world/data_pack/__init__.py +2 -2
  78. amulet/level/formats/anvil_world/data_pack/data_pack.py +224 -224
  79. amulet/level/formats/anvil_world/data_pack/data_pack_manager.py +77 -77
  80. amulet/level/formats/anvil_world/dimension.py +177 -177
  81. amulet/level/formats/anvil_world/format.py +769 -769
  82. amulet/level/formats/anvil_world/region.py +384 -384
  83. amulet/level/formats/construction/__init__.py +3 -3
  84. amulet/level/formats/construction/format_wrapper.py +515 -515
  85. amulet/level/formats/construction/interface.py +134 -134
  86. amulet/level/formats/construction/section.py +60 -60
  87. amulet/level/formats/construction/util.py +165 -165
  88. amulet/level/formats/leveldb_world/__init__.py +3 -3
  89. amulet/level/formats/leveldb_world/chunk.py +33 -33
  90. amulet/level/formats/leveldb_world/dimension.py +385 -419
  91. amulet/level/formats/leveldb_world/format.py +659 -641
  92. amulet/level/formats/leveldb_world/interface/chunk/__init__.py +36 -36
  93. amulet/level/formats/leveldb_world/interface/chunk/base_leveldb_interface.py +836 -836
  94. amulet/level/formats/leveldb_world/interface/chunk/generate_interface.py +31 -31
  95. amulet/level/formats/leveldb_world/interface/chunk/leveldb_0.py +30 -30
  96. amulet/level/formats/leveldb_world/interface/chunk/leveldb_1.py +12 -12
  97. amulet/level/formats/leveldb_world/interface/chunk/leveldb_10.py +12 -12
  98. amulet/level/formats/leveldb_world/interface/chunk/leveldb_11.py +12 -12
  99. amulet/level/formats/leveldb_world/interface/chunk/leveldb_12.py +12 -12
  100. amulet/level/formats/leveldb_world/interface/chunk/leveldb_13.py +12 -12
  101. amulet/level/formats/leveldb_world/interface/chunk/leveldb_14.py +12 -12
  102. amulet/level/formats/leveldb_world/interface/chunk/leveldb_15.py +12 -12
  103. amulet/level/formats/leveldb_world/interface/chunk/leveldb_16.py +12 -12
  104. amulet/level/formats/leveldb_world/interface/chunk/leveldb_17.py +12 -12
  105. amulet/level/formats/leveldb_world/interface/chunk/leveldb_18.py +12 -12
  106. amulet/level/formats/leveldb_world/interface/chunk/leveldb_19.py +12 -12
  107. amulet/level/formats/leveldb_world/interface/chunk/leveldb_2.py +12 -12
  108. amulet/level/formats/leveldb_world/interface/chunk/leveldb_20.py +12 -12
  109. amulet/level/formats/leveldb_world/interface/chunk/leveldb_21.py +12 -12
  110. amulet/level/formats/leveldb_world/interface/chunk/leveldb_22.py +12 -12
  111. amulet/level/formats/leveldb_world/interface/chunk/leveldb_23.py +10 -10
  112. amulet/level/formats/leveldb_world/interface/chunk/leveldb_24.py +10 -10
  113. amulet/level/formats/leveldb_world/interface/chunk/leveldb_25.py +24 -24
  114. amulet/level/formats/leveldb_world/interface/chunk/leveldb_26.py +10 -10
  115. amulet/level/formats/leveldb_world/interface/chunk/leveldb_27.py +10 -10
  116. amulet/level/formats/leveldb_world/interface/chunk/leveldb_28.py +10 -10
  117. amulet/level/formats/leveldb_world/interface/chunk/leveldb_29.py +33 -33
  118. amulet/level/formats/leveldb_world/interface/chunk/leveldb_3.py +57 -57
  119. amulet/level/formats/leveldb_world/interface/chunk/leveldb_30.py +10 -10
  120. amulet/level/formats/leveldb_world/interface/chunk/leveldb_31.py +10 -10
  121. amulet/level/formats/leveldb_world/interface/chunk/leveldb_32.py +10 -10
  122. amulet/level/formats/leveldb_world/interface/chunk/leveldb_33.py +10 -10
  123. amulet/level/formats/leveldb_world/interface/chunk/leveldb_34.py +10 -10
  124. amulet/level/formats/leveldb_world/interface/chunk/leveldb_35.py +10 -10
  125. amulet/level/formats/leveldb_world/interface/chunk/leveldb_36.py +10 -10
  126. amulet/level/formats/leveldb_world/interface/chunk/leveldb_37.py +10 -10
  127. amulet/level/formats/leveldb_world/interface/chunk/leveldb_38.py +10 -10
  128. amulet/level/formats/leveldb_world/interface/chunk/leveldb_39.py +12 -12
  129. amulet/level/formats/leveldb_world/interface/chunk/leveldb_4.py +12 -12
  130. amulet/level/formats/leveldb_world/interface/chunk/leveldb_40.py +16 -16
  131. amulet/level/formats/leveldb_world/interface/chunk/leveldb_5.py +12 -12
  132. amulet/level/formats/leveldb_world/interface/chunk/leveldb_6.py +12 -12
  133. amulet/level/formats/leveldb_world/interface/chunk/leveldb_7.py +12 -12
  134. amulet/level/formats/leveldb_world/interface/chunk/leveldb_8.py +180 -180
  135. amulet/level/formats/leveldb_world/interface/chunk/leveldb_9.py +18 -18
  136. amulet/level/formats/leveldb_world/interface/chunk/leveldb_chunk_versions.py +79 -79
  137. amulet/level/formats/mcstructure/__init__.py +3 -3
  138. amulet/level/formats/mcstructure/chunk.py +50 -50
  139. amulet/level/formats/mcstructure/format_wrapper.py +408 -408
  140. amulet/level/formats/mcstructure/interface.py +175 -175
  141. amulet/level/formats/schematic/__init__.py +3 -3
  142. amulet/level/formats/schematic/chunk.py +55 -55
  143. amulet/level/formats/schematic/data_types.py +4 -4
  144. amulet/level/formats/schematic/format_wrapper.py +373 -373
  145. amulet/level/formats/schematic/interface.py +142 -142
  146. amulet/level/formats/sponge_schem/__init__.py +4 -4
  147. amulet/level/formats/sponge_schem/chunk.py +62 -62
  148. amulet/level/formats/sponge_schem/format_wrapper.py +463 -463
  149. amulet/level/formats/sponge_schem/interface.py +118 -118
  150. amulet/level/formats/sponge_schem/varint/__init__.py +1 -1
  151. amulet/level/formats/sponge_schem/varint/varint.py +87 -87
  152. amulet/level/interfaces/chunk/anvil/anvil_0.py +72 -72
  153. amulet/level/interfaces/chunk/anvil/anvil_1444.py +336 -336
  154. amulet/level/interfaces/chunk/anvil/anvil_1466.py +94 -94
  155. amulet/level/interfaces/chunk/anvil/anvil_1467.py +37 -37
  156. amulet/level/interfaces/chunk/anvil/anvil_1484.py +20 -20
  157. amulet/level/interfaces/chunk/anvil/anvil_1503.py +20 -20
  158. amulet/level/interfaces/chunk/anvil/anvil_1519.py +34 -34
  159. amulet/level/interfaces/chunk/anvil/anvil_1901.py +20 -20
  160. amulet/level/interfaces/chunk/anvil/anvil_1908.py +20 -20
  161. amulet/level/interfaces/chunk/anvil/anvil_1912.py +21 -21
  162. amulet/level/interfaces/chunk/anvil/anvil_1934.py +20 -20
  163. amulet/level/interfaces/chunk/anvil/anvil_2203.py +69 -69
  164. amulet/level/interfaces/chunk/anvil/anvil_2529.py +19 -19
  165. amulet/level/interfaces/chunk/anvil/anvil_2681.py +76 -76
  166. amulet/level/interfaces/chunk/anvil/anvil_2709.py +19 -19
  167. amulet/level/interfaces/chunk/anvil/anvil_2844.py +267 -267
  168. amulet/level/interfaces/chunk/anvil/anvil_3463.py +19 -19
  169. amulet/level/interfaces/chunk/anvil/anvil_na.py +607 -607
  170. amulet/level/interfaces/chunk/anvil/base_anvil_interface.py +326 -326
  171. amulet/level/load.py +59 -59
  172. amulet/level/loader.py +95 -95
  173. amulet/level/translators/chunk/bedrock/__init__.py +267 -267
  174. amulet/level/translators/chunk/bedrock/bedrock_nbt_blockstate_translator.py +46 -46
  175. amulet/level/translators/chunk/bedrock/bedrock_numerical_translator.py +39 -39
  176. amulet/level/translators/chunk/bedrock/bedrock_psudo_numerical_translator.py +37 -37
  177. amulet/level/translators/chunk/java/java_1_18_translator.py +40 -40
  178. amulet/level/translators/chunk/java/java_blockstate_translator.py +94 -94
  179. amulet/level/translators/chunk/java/java_numerical_translator.py +62 -62
  180. amulet/libs/leveldb/__init__.py +7 -7
  181. amulet/operations/__init__.py +5 -5
  182. amulet/operations/clone.py +18 -18
  183. amulet/operations/delete_chunk.py +32 -32
  184. amulet/operations/fill.py +30 -30
  185. amulet/operations/paste.py +65 -65
  186. amulet/operations/replace.py +58 -58
  187. amulet/utils/__init__.py +14 -14
  188. amulet/utils/format_utils.py +41 -41
  189. amulet/utils/generator.py +15 -15
  190. amulet/utils/matrix.py +243 -243
  191. amulet/utils/numpy_helpers.py +46 -46
  192. amulet/utils/world_utils.py +349 -349
  193. {amulet_core-1.9.19.dist-info → amulet_core-1.9.20.dist-info}/METADATA +97 -97
  194. amulet_core-1.9.20.dist-info/RECORD +208 -0
  195. amulet_core-1.9.19.dist-info/RECORD +0 -208
  196. {amulet_core-1.9.19.dist-info → amulet_core-1.9.20.dist-info}/WHEEL +0 -0
  197. {amulet_core-1.9.19.dist-info → amulet_core-1.9.20.dist-info}/entry_points.txt +0 -0
  198. {amulet_core-1.9.19.dist-info → amulet_core-1.9.20.dist-info}/top_level.txt +0 -0
@@ -1,267 +1,267 @@
1
- from __future__ import annotations
2
-
3
- from typing import Optional, TYPE_CHECKING
4
- import logging
5
- import numpy
6
-
7
- from amulet_nbt import IntTag
8
-
9
-
10
- from amulet.api.block import Block
11
- from amulet.api.registry import BlockManager
12
- from amulet.api.entity import Entity
13
- from amulet.api.wrapper.chunk.translator import Translator
14
- from amulet.api.data_types import (
15
- GetBlockCallback,
16
- TranslateBlockCallbackReturn,
17
- TranslateEntityCallbackReturn,
18
- VersionNumberTuple,
19
- GetChunkCallback,
20
- BedrockInterfaceBlockType,
21
- VersionIdentifierType,
22
- VersionNumberAny,
23
- BlockCoordinates,
24
- AnyNDArray,
25
- )
26
-
27
- if TYPE_CHECKING:
28
- from PyMCTranslate import TranslationManager
29
- from amulet.api.chunk import Chunk
30
-
31
- log = logging.getLogger(__name__)
32
-
33
-
34
- class BaseBedrockTranslator(Translator):
35
- def _translator_key(
36
- self, version_number: VersionNumberAny
37
- ) -> VersionIdentifierType:
38
- return "bedrock", version_number
39
-
40
- @staticmethod
41
- def _unpack_blocks(
42
- translation_manager: "TranslationManager",
43
- version_identifier: VersionIdentifierType,
44
- chunk: Chunk,
45
- block_palette: AnyNDArray,
46
- ):
47
- """
48
- Unpacks an object array of block data into a numpy object array containing Block objects.
49
- :param translation_manager:
50
- :param version_identifier:
51
- :param chunk:
52
- :param block_palette:
53
- :type block_palette: numpy.ndarray[
54
- Tuple[
55
- Union[
56
- Tuple[None, Tuple[int, int]],
57
- Tuple[None, Block],
58
- Tuple[int, Block]
59
- ], ...
60
- ]
61
- ]
62
- :return:
63
- """
64
- palette_ = BlockManager()
65
- lut = []
66
- for palette_index, entry in enumerate(block_palette):
67
- entry: BedrockInterfaceBlockType
68
- block = None
69
- for version_number, b in entry:
70
- version_number: Optional[int]
71
- if isinstance(b, tuple):
72
- version = translation_manager.get_version(
73
- version_identifier[0], version_number or 17563649
74
- )
75
- b = version.block.ints_to_block(*b)
76
- elif isinstance(b, Block):
77
- if version_number is not None:
78
- properties = b.properties
79
- properties["__version__"] = IntTag(version_number)
80
- b = Block(b.namespace, b.base_name, properties, b.extra_blocks)
81
- else:
82
- raise Exception(f"Unsupported type {b}")
83
- if block is None:
84
- block = b
85
- else:
86
- block += b
87
- if block is None:
88
- raise Exception(f"Empty tuple")
89
-
90
- lut.append(palette_.get_add_block(block))
91
- chunk._block_palette = palette_
92
-
93
- if len(palette_) != len(lut):
94
- # sometimes a block can be stored in different formats but unpack to the same block
95
- # this means that the final palette is smaller than the original so the array needs remapping
96
- np_lut = numpy.array(lut)
97
- for cy in chunk.blocks.sub_chunks:
98
- chunk.blocks.add_sub_chunk(cy, np_lut[chunk.blocks.get_sub_chunk(cy)])
99
-
100
- def _blocks_entities_to_universal(
101
- self,
102
- game_version: VersionNumberTuple,
103
- translation_manager: "TranslationManager",
104
- chunk: Chunk,
105
- get_chunk_callback: Optional[GetChunkCallback],
106
- full_translate: bool,
107
- ):
108
- # Bedrock does versioning by block rather than by chunk.
109
- # As such we can't just pass in a single translator.
110
- # It needs to be done dynamically.
111
- versions = {}
112
-
113
- def translate_block(
114
- input_object: Block,
115
- get_block_callback: Optional[GetBlockCallback],
116
- block_location: BlockCoordinates,
117
- ) -> TranslateBlockCallbackReturn:
118
- final_block = None
119
- final_block_entity = None
120
- final_entities = []
121
- final_extra = False
122
-
123
- for depth, block in enumerate(input_object.block_tuple):
124
- properties = dict(block.properties)
125
- if "__version__" in properties:
126
- game_version_: int = int(properties.pop("__version__"))
127
- block = Block(block.namespace, block.base_name, properties)
128
- elif "block_data" in properties:
129
- # if block_data is in properties cap out at 1.12.x
130
- game_version_: VersionNumberTuple = min(game_version, (1, 12, 999))
131
- else:
132
- game_version_: VersionNumberTuple = game_version
133
- version_key = self._translator_key(game_version_)
134
- if version_key not in versions:
135
- versions[version_key] = translation_manager.get_version(
136
- *version_key
137
- ).block.to_universal
138
- output_object, output_block_entity, extra = versions[version_key](
139
- block,
140
- get_block_callback=get_block_callback,
141
- block_location=block_location,
142
- )
143
-
144
- if isinstance(output_object, Block):
145
- if not output_object.namespace.startswith("universal"):
146
- log.debug(
147
- f"Error translating {block.full_blockstate} to universal. Got {output_object.full_blockstate}"
148
- )
149
- if final_block is None:
150
- final_block = output_object
151
- else:
152
- final_block += output_object
153
- if depth == 0:
154
- final_block_entity = output_block_entity
155
-
156
- elif isinstance(output_object, Entity):
157
- final_entities.append(output_object)
158
- # TODO: offset entity coords
159
-
160
- final_extra |= extra
161
-
162
- return final_block, final_block_entity, final_entities, final_extra
163
-
164
- def translate_entity(input_object: Entity) -> TranslateEntityCallbackReturn:
165
- final_block = None
166
- final_block_entity = None
167
- final_entities = []
168
- # TODO
169
- return final_block, final_block_entity, final_entities
170
-
171
- version = translation_manager.get_version(*self._translator_key(game_version))
172
-
173
- self._translate(
174
- chunk,
175
- get_chunk_callback,
176
- translate_block,
177
- translate_entity,
178
- full_translate,
179
- )
180
-
181
- def _blocks_entities_from_universal(
182
- self,
183
- max_world_version_number: VersionNumberAny,
184
- translation_manager: "TranslationManager",
185
- chunk: Chunk,
186
- get_chunk_callback: Optional[GetChunkCallback],
187
- full_translate: bool,
188
- ):
189
- """
190
- Translate a universal chunk into the interface-specific format.
191
-
192
- :param max_world_version_number: The version number (int or tuple) of the max world version
193
- :param translation_manager: TranslationManager used for the translation
194
- :param chunk: The chunk to translate.
195
- :param get_chunk_callback: function callback to get a chunk's data
196
- :param full_translate: if true do a full translate. If false just pack the block_palette (used in callback)
197
- :return: Chunk object in the interface-specific format and block_palette.
198
- """
199
- version = translation_manager.get_version(
200
- *self._translator_key(max_world_version_number)
201
- )
202
-
203
- # TODO: perhaps find a way so this code isn't duplicated in three places
204
- def translate_block(
205
- input_object: Block,
206
- get_block_callback: Optional[GetBlockCallback],
207
- block_location: BlockCoordinates,
208
- ) -> TranslateBlockCallbackReturn:
209
- final_block = None
210
- final_block_entity = None
211
- final_entities = []
212
- final_extra = False
213
-
214
- for depth, block in enumerate(input_object.block_tuple):
215
- (
216
- output_object,
217
- output_block_entity,
218
- extra,
219
- ) = version.block.from_universal(
220
- block,
221
- get_block_callback=get_block_callback,
222
- block_location=block_location,
223
- )
224
-
225
- if isinstance(output_object, Block):
226
- if __debug__ and output_object.namespace.startswith("universal"):
227
- log.debug(
228
- f"Error translating {input_object.full_blockstate} from universal. Got {output_object.full_blockstate}"
229
- )
230
- if version.data_version > 0:
231
- properties = output_object.properties
232
- properties["__version__"] = IntTag(version.data_version)
233
- output_object = Block(
234
- output_object.namespace,
235
- output_object.base_name,
236
- properties,
237
- output_object.extra_blocks,
238
- )
239
- if final_block is None:
240
- final_block = output_object
241
- else:
242
- final_block += output_object
243
- if depth == 0:
244
- final_block_entity = output_block_entity
245
-
246
- elif isinstance(output_object, Entity):
247
- final_entities.append(output_object)
248
- # TODO: offset entity coords
249
-
250
- final_extra |= extra
251
-
252
- return final_block, final_block_entity, final_entities, final_extra
253
-
254
- def translate_entity(input_object: Entity) -> TranslateEntityCallbackReturn:
255
- final_block = None
256
- final_block_entity = None
257
- final_entities = []
258
- # TODO
259
- return final_block, final_block_entity, final_entities
260
-
261
- self._translate(
262
- chunk,
263
- get_chunk_callback,
264
- translate_block,
265
- translate_entity,
266
- full_translate,
267
- )
1
+ from __future__ import annotations
2
+
3
+ from typing import Optional, TYPE_CHECKING
4
+ import logging
5
+ import numpy
6
+
7
+ from amulet_nbt import IntTag
8
+
9
+
10
+ from amulet.api.block import Block
11
+ from amulet.api.registry import BlockManager
12
+ from amulet.api.entity import Entity
13
+ from amulet.api.wrapper.chunk.translator import Translator
14
+ from amulet.api.data_types import (
15
+ GetBlockCallback,
16
+ TranslateBlockCallbackReturn,
17
+ TranslateEntityCallbackReturn,
18
+ VersionNumberTuple,
19
+ GetChunkCallback,
20
+ BedrockInterfaceBlockType,
21
+ VersionIdentifierType,
22
+ VersionNumberAny,
23
+ BlockCoordinates,
24
+ AnyNDArray,
25
+ )
26
+
27
+ if TYPE_CHECKING:
28
+ from PyMCTranslate import TranslationManager
29
+ from amulet.api.chunk import Chunk
30
+
31
+ log = logging.getLogger(__name__)
32
+
33
+
34
+ class BaseBedrockTranslator(Translator):
35
+ def _translator_key(
36
+ self, version_number: VersionNumberAny
37
+ ) -> VersionIdentifierType:
38
+ return "bedrock", version_number
39
+
40
+ @staticmethod
41
+ def _unpack_blocks(
42
+ translation_manager: "TranslationManager",
43
+ version_identifier: VersionIdentifierType,
44
+ chunk: Chunk,
45
+ block_palette: AnyNDArray,
46
+ ):
47
+ """
48
+ Unpacks an object array of block data into a numpy object array containing Block objects.
49
+ :param translation_manager:
50
+ :param version_identifier:
51
+ :param chunk:
52
+ :param block_palette:
53
+ :type block_palette: numpy.ndarray[
54
+ Tuple[
55
+ Union[
56
+ Tuple[None, Tuple[int, int]],
57
+ Tuple[None, Block],
58
+ Tuple[int, Block]
59
+ ], ...
60
+ ]
61
+ ]
62
+ :return:
63
+ """
64
+ palette_ = BlockManager()
65
+ lut = []
66
+ for palette_index, entry in enumerate(block_palette):
67
+ entry: BedrockInterfaceBlockType
68
+ block = None
69
+ for version_number, b in entry:
70
+ version_number: Optional[int]
71
+ if isinstance(b, tuple):
72
+ version = translation_manager.get_version(
73
+ version_identifier[0], version_number or 17563649
74
+ )
75
+ b = version.block.ints_to_block(*b)
76
+ elif isinstance(b, Block):
77
+ if version_number is not None:
78
+ properties = b.properties
79
+ properties["__version__"] = IntTag(version_number)
80
+ b = Block(b.namespace, b.base_name, properties, b.extra_blocks)
81
+ else:
82
+ raise Exception(f"Unsupported type {b}")
83
+ if block is None:
84
+ block = b
85
+ else:
86
+ block += b
87
+ if block is None:
88
+ raise Exception(f"Empty tuple")
89
+
90
+ lut.append(palette_.get_add_block(block))
91
+ chunk._block_palette = palette_
92
+
93
+ if len(palette_) != len(lut):
94
+ # sometimes a block can be stored in different formats but unpack to the same block
95
+ # this means that the final palette is smaller than the original so the array needs remapping
96
+ np_lut = numpy.array(lut)
97
+ for cy in chunk.blocks.sub_chunks:
98
+ chunk.blocks.add_sub_chunk(cy, np_lut[chunk.blocks.get_sub_chunk(cy)])
99
+
100
+ def _blocks_entities_to_universal(
101
+ self,
102
+ game_version: VersionNumberTuple,
103
+ translation_manager: "TranslationManager",
104
+ chunk: Chunk,
105
+ get_chunk_callback: Optional[GetChunkCallback],
106
+ full_translate: bool,
107
+ ):
108
+ # Bedrock does versioning by block rather than by chunk.
109
+ # As such we can't just pass in a single translator.
110
+ # It needs to be done dynamically.
111
+ versions = {}
112
+
113
+ def translate_block(
114
+ input_object: Block,
115
+ get_block_callback: Optional[GetBlockCallback],
116
+ block_location: BlockCoordinates,
117
+ ) -> TranslateBlockCallbackReturn:
118
+ final_block = None
119
+ final_block_entity = None
120
+ final_entities = []
121
+ final_extra = False
122
+
123
+ for depth, block in enumerate(input_object.block_tuple):
124
+ properties = dict(block.properties)
125
+ if "__version__" in properties:
126
+ game_version_: int = int(properties.pop("__version__"))
127
+ block = Block(block.namespace, block.base_name, properties)
128
+ elif "block_data" in properties:
129
+ # if block_data is in properties cap out at 1.12.x
130
+ game_version_: VersionNumberTuple = min(game_version, (1, 12, 999))
131
+ else:
132
+ game_version_: VersionNumberTuple = game_version
133
+ version_key = self._translator_key(game_version_)
134
+ if version_key not in versions:
135
+ versions[version_key] = translation_manager.get_version(
136
+ *version_key
137
+ ).block.to_universal
138
+ output_object, output_block_entity, extra = versions[version_key](
139
+ block,
140
+ get_block_callback=get_block_callback,
141
+ block_location=block_location,
142
+ )
143
+
144
+ if isinstance(output_object, Block):
145
+ if not output_object.namespace.startswith("universal"):
146
+ log.debug(
147
+ f"Error translating {block.full_blockstate} to universal. Got {output_object.full_blockstate}"
148
+ )
149
+ if final_block is None:
150
+ final_block = output_object
151
+ else:
152
+ final_block += output_object
153
+ if depth == 0:
154
+ final_block_entity = output_block_entity
155
+
156
+ elif isinstance(output_object, Entity):
157
+ final_entities.append(output_object)
158
+ # TODO: offset entity coords
159
+
160
+ final_extra |= extra
161
+
162
+ return final_block, final_block_entity, final_entities, final_extra
163
+
164
+ def translate_entity(input_object: Entity) -> TranslateEntityCallbackReturn:
165
+ final_block = None
166
+ final_block_entity = None
167
+ final_entities = []
168
+ # TODO
169
+ return final_block, final_block_entity, final_entities
170
+
171
+ version = translation_manager.get_version(*self._translator_key(game_version))
172
+
173
+ self._translate(
174
+ chunk,
175
+ get_chunk_callback,
176
+ translate_block,
177
+ translate_entity,
178
+ full_translate,
179
+ )
180
+
181
+ def _blocks_entities_from_universal(
182
+ self,
183
+ max_world_version_number: VersionNumberAny,
184
+ translation_manager: "TranslationManager",
185
+ chunk: Chunk,
186
+ get_chunk_callback: Optional[GetChunkCallback],
187
+ full_translate: bool,
188
+ ):
189
+ """
190
+ Translate a universal chunk into the interface-specific format.
191
+
192
+ :param max_world_version_number: The version number (int or tuple) of the max world version
193
+ :param translation_manager: TranslationManager used for the translation
194
+ :param chunk: The chunk to translate.
195
+ :param get_chunk_callback: function callback to get a chunk's data
196
+ :param full_translate: if true do a full translate. If false just pack the block_palette (used in callback)
197
+ :return: Chunk object in the interface-specific format and block_palette.
198
+ """
199
+ version = translation_manager.get_version(
200
+ *self._translator_key(max_world_version_number)
201
+ )
202
+
203
+ # TODO: perhaps find a way so this code isn't duplicated in three places
204
+ def translate_block(
205
+ input_object: Block,
206
+ get_block_callback: Optional[GetBlockCallback],
207
+ block_location: BlockCoordinates,
208
+ ) -> TranslateBlockCallbackReturn:
209
+ final_block = None
210
+ final_block_entity = None
211
+ final_entities = []
212
+ final_extra = False
213
+
214
+ for depth, block in enumerate(input_object.block_tuple):
215
+ (
216
+ output_object,
217
+ output_block_entity,
218
+ extra,
219
+ ) = version.block.from_universal(
220
+ block,
221
+ get_block_callback=get_block_callback,
222
+ block_location=block_location,
223
+ )
224
+
225
+ if isinstance(output_object, Block):
226
+ if __debug__ and output_object.namespace.startswith("universal"):
227
+ log.debug(
228
+ f"Error translating {input_object.full_blockstate} from universal. Got {output_object.full_blockstate}"
229
+ )
230
+ if version.data_version > 0:
231
+ properties = output_object.properties
232
+ properties["__version__"] = IntTag(version.data_version)
233
+ output_object = Block(
234
+ output_object.namespace,
235
+ output_object.base_name,
236
+ properties,
237
+ output_object.extra_blocks,
238
+ )
239
+ if final_block is None:
240
+ final_block = output_object
241
+ else:
242
+ final_block += output_object
243
+ if depth == 0:
244
+ final_block_entity = output_block_entity
245
+
246
+ elif isinstance(output_object, Entity):
247
+ final_entities.append(output_object)
248
+ # TODO: offset entity coords
249
+
250
+ final_extra |= extra
251
+
252
+ return final_block, final_block_entity, final_entities, final_extra
253
+
254
+ def translate_entity(input_object: Entity) -> TranslateEntityCallbackReturn:
255
+ final_block = None
256
+ final_block_entity = None
257
+ final_entities = []
258
+ # TODO
259
+ return final_block, final_block_entity, final_entities
260
+
261
+ self._translate(
262
+ chunk,
263
+ get_chunk_callback,
264
+ translate_block,
265
+ translate_entity,
266
+ full_translate,
267
+ )
@@ -1,46 +1,46 @@
1
- from __future__ import annotations
2
-
3
- import numpy
4
- from typing import TYPE_CHECKING
5
-
6
- from amulet.level.translators.chunk.bedrock import BaseBedrockTranslator
7
- from amulet.api.data_types import BlockNDArray, AnyNDArray
8
- from amulet.api.block import Block
9
-
10
- if TYPE_CHECKING:
11
- from PyMCTranslate import Version
12
-
13
-
14
- class BedrockNBTBlockstateTranslator(BaseBedrockTranslator):
15
- @staticmethod
16
- def is_valid(key):
17
- return key[0] == "bedrock" and (1, 13, 0) <= key[1]
18
-
19
- def _pack_block_palette(
20
- self, version: "Version", palette: BlockNDArray
21
- ) -> AnyNDArray:
22
- """
23
- Packs a numpy array of Block objects into an object array containing one more more pairs of version number and Block objects.
24
- :param version:
25
- :param palette:
26
- :return: numpy.ndarray[Tuple[Tuple[Optional[VersionNumber], Block], ...]]
27
- """
28
- palette_ = numpy.empty(len(palette), dtype=object)
29
- for palette_index, block in enumerate(palette):
30
- block: "Block"
31
- # TODO: perhaps check that all properties are NBT objects user interaction if not
32
- blocks = []
33
- for b in block.block_tuple:
34
- if "__version__" in b.properties:
35
- properties = b.properties
36
- version_number = properties.pop("__version__").py_int
37
- b = Block(b.namespace, b.base_name, properties, b.extra_blocks)
38
- else:
39
- version_number = None
40
- blocks.append((version_number, b))
41
- palette_[palette_index] = tuple(blocks)
42
-
43
- return palette_
44
-
45
-
46
- export = BedrockNBTBlockstateTranslator
1
+ from __future__ import annotations
2
+
3
+ import numpy
4
+ from typing import TYPE_CHECKING
5
+
6
+ from amulet.level.translators.chunk.bedrock import BaseBedrockTranslator
7
+ from amulet.api.data_types import BlockNDArray, AnyNDArray
8
+ from amulet.api.block import Block
9
+
10
+ if TYPE_CHECKING:
11
+ from PyMCTranslate import Version
12
+
13
+
14
+ class BedrockNBTBlockstateTranslator(BaseBedrockTranslator):
15
+ @staticmethod
16
+ def is_valid(key):
17
+ return key[0] == "bedrock" and (1, 13, 0) <= key[1]
18
+
19
+ def _pack_block_palette(
20
+ self, version: "Version", palette: BlockNDArray
21
+ ) -> AnyNDArray:
22
+ """
23
+ Packs a numpy array of Block objects into an object array containing one more more pairs of version number and Block objects.
24
+ :param version:
25
+ :param palette:
26
+ :return: numpy.ndarray[Tuple[Tuple[Optional[VersionNumber], Block], ...]]
27
+ """
28
+ palette_ = numpy.empty(len(palette), dtype=object)
29
+ for palette_index, block in enumerate(palette):
30
+ block: "Block"
31
+ # TODO: perhaps check that all properties are NBT objects user interaction if not
32
+ blocks = []
33
+ for b in block.block_tuple:
34
+ if "__version__" in b.properties:
35
+ properties = b.properties
36
+ version_number = properties.pop("__version__").py_int
37
+ b = Block(b.namespace, b.base_name, properties, b.extra_blocks)
38
+ else:
39
+ version_number = None
40
+ blocks.append((version_number, b))
41
+ palette_[palette_index] = tuple(blocks)
42
+
43
+ return palette_
44
+
45
+
46
+ export = BedrockNBTBlockstateTranslator