amulet-core 2.0a3__cp312-cp312-win_amd64.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__.cp312-win_amd64.pyd +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.0a3.dist-info/METADATA +103 -0
  207. amulet_core-2.0a3.dist-info/RECORD +210 -0
  208. amulet_core-2.0a3.dist-info/WHEEL +5 -0
  209. amulet_core-2.0a3.dist-info/entry_points.txt +2 -0
  210. amulet_core-2.0a3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,463 @@
1
+ from __future__ import annotations
2
+ from typing import TYPE_CHECKING, Callable
3
+ from functools import cache
4
+ import logging
5
+
6
+ import numpy
7
+ from amulet_nbt import (
8
+ NamedTag,
9
+ AbstractBaseIntTag,
10
+ ByteTag,
11
+ ShortTag,
12
+ IntTag,
13
+ LongTag,
14
+ FloatTag,
15
+ DoubleTag,
16
+ StringTag,
17
+ CompoundTag,
18
+ ListTag,
19
+ ByteArrayTag,
20
+ IntArrayTag,
21
+ LongArrayTag,
22
+ )
23
+
24
+ from amulet.game import get_game_version
25
+ from amulet.game.java import JavaGameVersion, Waterloggable
26
+ from amulet.utils.world_utils import encode_long_array, to_nibble_array
27
+ from amulet.utils.numpy import unique_inverse
28
+
29
+ from amulet.block import Block, BlockStack
30
+ from amulet.biome import Biome
31
+ from amulet.block_entity import BlockEntity
32
+ from amulet.entity import Entity
33
+ from amulet.version import VersionNumber, VersionRange
34
+ from amulet.palette import BlockPalette
35
+
36
+ from amulet.chunk.components.height_2d import Height2DComponent
37
+ from amulet.chunk.components.biome import (
38
+ Biome2DComponent,
39
+ Biome2DComponentData,
40
+ Biome3DComponent,
41
+ Biome3DComponentData,
42
+ )
43
+ from amulet.chunk.components.block import BlockComponent, BlockComponentData
44
+ from amulet.chunk.components.sub_chunk_array import SubChunkArrayContainer
45
+ from amulet.chunk.components.block_entity import (
46
+ BlockEntityComponent,
47
+ BlockEntityComponentData,
48
+ )
49
+ from amulet.chunk.components.entity import EntityComponent, EntityComponentData
50
+
51
+ from amulet.level.java.anvil import RawChunkType
52
+ from amulet.level.java.chunk import JavaChunk
53
+
54
+ from amulet.level.java.chunk.components.raw_chunk import RawChunkComponent
55
+ from amulet.level.java.chunk.components.data_version import DataVersionComponent
56
+ from amulet.level.java.chunk.components.legacy_version import LegacyVersionComponent
57
+ from amulet.level.java.chunk.components.status import StatusComponent
58
+ from amulet.level.java.chunk.components.light_populated import LightPopulatedComponent
59
+ from amulet.level.java.chunk.components.terrain_populated import (
60
+ TerrainPopulatedComponent,
61
+ )
62
+ from amulet.level.java.chunk.components.named_height_2d import (
63
+ NamedHeight2DComponent,
64
+ NamedHeight2DData,
65
+ )
66
+ from amulet.level.java.chunk.components.last_update import LastUpdateComponent
67
+ from amulet.level.java.chunk.components.inhabited_time import InhabitedTimeComponent
68
+
69
+ if TYPE_CHECKING:
70
+ from ._level import JavaRawLevel
71
+ from ._dimension import JavaRawDimension
72
+
73
+
74
+ log = logging.getLogger(__name__)
75
+
76
+
77
+ def native_to_raw(
78
+ raw_level: JavaRawLevel,
79
+ dimension: JavaRawDimension,
80
+ chunk: JavaChunk,
81
+ cx: int,
82
+ cz: int,
83
+ ) -> RawChunkType:
84
+ bounds = dimension.bounds().bounding_box()
85
+ height = bounds.size_y
86
+
87
+ # Get the data version. All Java chunk classes must have this
88
+ data_version = chunk.get_component(DataVersionComponent)
89
+ game_version = get_game_version("java", VersionNumber(data_version))
90
+
91
+ # Pull out or create the raw chunk data
92
+ raw_chunk_component = chunk.get_component(RawChunkComponent)
93
+ if raw_chunk_component is None:
94
+ raw_chunk = {}
95
+ else:
96
+ raw_chunk = raw_chunk_component
97
+
98
+ # Set up the region and level objects
99
+ region = raw_chunk.setdefault("region", NamedTag()).compound
100
+ if data_version >= 2844:
101
+ # This should be unused
102
+ level = CompoundTag()
103
+ else:
104
+ level = region.setdefault_compound("Level")
105
+
106
+ if data_version >= 0:
107
+ region["DataVersion"] = IntTag(data_version)
108
+ else:
109
+ region["V"] = ByteTag(chunk.get_component(LegacyVersionComponent))
110
+
111
+ # Chunk x and y pos
112
+ if data_version >= 2844:
113
+ region["xPos"] = IntTag(cx)
114
+ floor_cy = bounds.min_y >> 4
115
+ region["yPos"] = IntTag(floor_cy)
116
+ ceil_cy = bounds.max_y >> 4
117
+ region["zPos"] = IntTag(cz)
118
+ else:
119
+ level["xPos"] = IntTag(cx)
120
+ floor_cy = 0
121
+ ceil_cy = 16
122
+ level["zPos"] = IntTag(cz)
123
+
124
+ # LastUpdate
125
+ if data_version >= 2844:
126
+ region["LastUpdate"] = LongTag(chunk.get_component(LastUpdateComponent))
127
+ region["InhabitedTime"] = LongTag(chunk.get_component(InhabitedTimeComponent))
128
+ else:
129
+ level["LastUpdate"] = LongTag(chunk.get_component(LastUpdateComponent))
130
+ level["InhabitedTime"] = LongTag(chunk.get_component(InhabitedTimeComponent))
131
+
132
+ # Status
133
+ if data_version >= 2844:
134
+ region["Status"] = StringTag(chunk.get_component(StatusComponent))
135
+ elif data_version >= 1444:
136
+ level["Status"] = StringTag(chunk.get_component(StatusComponent))
137
+ else:
138
+ level["TerrainPopulated"] = ByteTag(
139
+ chunk.get_component(TerrainPopulatedComponent)
140
+ )
141
+ level["LightPopulated"] = ByteTag(chunk.get_component(LightPopulatedComponent))
142
+
143
+ # Height map
144
+ if data_version >= 1466:
145
+ height_maps = CompoundTag(
146
+ {
147
+ key: LongArrayTag(
148
+ encode_long_array(
149
+ value.ravel() - (floor_cy << 4),
150
+ height.bit_length(),
151
+ data_version <= 2529,
152
+ )
153
+ )
154
+ for key, value in chunk.get_component(
155
+ NamedHeight2DComponent
156
+ ).arrays.items()
157
+ if isinstance(key, str)
158
+ and isinstance(value, numpy.ndarray)
159
+ and value.size == 256
160
+ }
161
+ )
162
+ if data_version >= 2844:
163
+ region["HeightMaps"] = height_maps
164
+ else:
165
+ level["HeightMaps"] = height_maps
166
+ else:
167
+ level["HeightMap"] = IntArrayTag(chunk.get_component(Height2DComponent).ravel())
168
+
169
+ # biomes
170
+ get_biome_id_override: Callable[[str, str], int] = (
171
+ raw_level.biome_id_override.namespace_id_to_numerical_id
172
+ )
173
+ get_biome_id_game: Callable[[str, str], int] = (
174
+ game_version.biome.namespace_id_to_numerical_id
175
+ )
176
+
177
+ @cache
178
+ def encode_biome(namespace: str, base_name: str) -> int:
179
+ try:
180
+ # First try overrides
181
+ return get_biome_id_override(namespace, base_name)
182
+ except KeyError:
183
+ try:
184
+ # Then fall back to the game implementation.
185
+ return get_biome_id_game(namespace, base_name)
186
+ except KeyError:
187
+ log.error(
188
+ f"Unknown biome {namespace}:{base_name}. Falling back to default."
189
+ )
190
+ default_biome = dimension.default_biome()
191
+ if (
192
+ namespace == default_biome.namespace
193
+ and base_name == default_biome.base_name
194
+ ):
195
+ return 0
196
+ return encode_biome(default_biome.namespace, default_biome.base_name)
197
+
198
+ if data_version >= 2844:
199
+ # region.sections[]
200
+ sections_tag = region.setdefault_list("sections")
201
+ else:
202
+ # region.Level.sections[]
203
+ sections_tag = level.setdefault_list("sections")
204
+ sections_map = {}
205
+ for section_tag in sections_tag:
206
+ assert isinstance(section_tag, CompoundTag)
207
+ sections_map[section_tag.get_byte("Y", ByteTag(0)).py_int] = section_tag
208
+
209
+ def get_section(cy_: int) -> CompoundTag:
210
+ section_tag_ = sections_map.get(cy_, None)
211
+ if section_tag_ is None:
212
+ section_tag_ = sections_map[cy_] = CompoundTag()
213
+ section_tag_["Y"] = ByteTag(cy_)
214
+ sections_tag.append(section_tag_)
215
+ return section_tag_
216
+
217
+ if data_version >= 2203:
218
+ # 3D
219
+ biome_data_3d: Biome3DComponentData = chunk.get_component(Biome3DComponent)
220
+ biome_sections: SubChunkArrayContainer = biome_data_3d.sections
221
+ palette = biome_data_3d.palette
222
+ if data_version >= 2836:
223
+ # Paletted
224
+ # if data_version >= 2844:
225
+ # # region.sections[].biomes.palette
226
+ # # region.sections[].biomes.data
227
+ # else:
228
+ # # region.Level.sections[].biomes.palette
229
+ # # region.Level.sections[].biomes.data
230
+
231
+ for cy in range(floor_cy, ceil_cy):
232
+ if cy not in biome_sections:
233
+ continue
234
+ arr = numpy.transpose(biome_sections[cy], (1, 2, 0)).ravel()
235
+ runtime_ids, arr = numpy.unique(arr, return_inverse=True)
236
+ sub_palette = ListTag(
237
+ [
238
+ StringTag(palette.index_to_biome(runtime_id).namespaced_name)
239
+ for runtime_id in runtime_ids
240
+ ]
241
+ )
242
+ section_tag = get_section(cy)
243
+ biomes = section_tag["biomes"] = CompoundTag({"palette": sub_palette})
244
+ if len(sub_palette) > 1:
245
+ biomes["data"] = LongArrayTag(
246
+ encode_long_array(arr, dense=data_version <= 2529)
247
+ )
248
+ else:
249
+ # hard coded ids
250
+ # region.Level.Biomes (4x64x4 IntArrayTag[1024])
251
+ arrays = []
252
+ for cy in range(floor_cy, ceil_cy):
253
+ if cy not in biome_sections:
254
+ biome_sections.populate(cy)
255
+ arrays.append(biome_sections[cy])
256
+ arr = numpy.transpose(
257
+ numpy.stack(arrays, 1, dtype=numpy.uint32),
258
+ (1, 2, 0),
259
+ ).ravel() # YZX -> XYZ
260
+ runtime_ids, arr = numpy.unique(arr, return_inverse=True)
261
+ numerical_ids = []
262
+ for rid in runtime_ids:
263
+ biome = palette.index_to_biome(rid)
264
+ numerical_ids.append(encode_biome(biome.namespace, biome.base_name))
265
+ level["Biomes"] = IntArrayTag(
266
+ numpy.asarray(numerical_ids, dtype=numpy.uint32)[arr]
267
+ )
268
+ else:
269
+ # 2D
270
+ biome_data_2d: Biome2DComponentData = chunk.get_component(Biome2DComponent)
271
+ runtime_ids, arr = numpy.unique(
272
+ biome_data_2d.array.ravel(), return_inverse=True
273
+ )
274
+ numerical_ids = []
275
+ for rid in runtime_ids:
276
+ biome = biome_data_2d.palette.index_to_biome(rid)
277
+ numerical_ids.append(encode_biome(biome.namespace, biome.base_name))
278
+ if data_version >= 1467:
279
+ # region.Level.Biomes (16x16 IntArrayTag[256])
280
+ level["Biomes"] = IntArrayTag(
281
+ numpy.asarray(numerical_ids, dtype=numpy.uint32)[arr]
282
+ )
283
+ else:
284
+ # region.Level.Biomes (16x16 ByteArrayTag[256])
285
+ level["Biomes"] = ByteArrayTag(
286
+ numpy.asarray(numerical_ids, dtype=numpy.uint8)[arr]
287
+ )
288
+
289
+ # blocks
290
+ block_component_data = chunk.get_component(BlockComponent)
291
+ block_palette: BlockPalette = block_component_data.palette
292
+ block_sections: SubChunkArrayContainer = block_component_data.sections
293
+
294
+ if data_version >= 1444:
295
+ # if data_version >= 2844:
296
+ # # region.sections[].block_states.data
297
+ # # region.sections[].block_states.palette
298
+ # elif data_version >= 2836:
299
+ # # region.Level.Sections[].block_states.data
300
+ # # region.Level.Sections[].block_states.palette
301
+ # else:
302
+ # # region.Level.Sections[].BlockStates
303
+ # # region.Level.Sections[].Palette
304
+ for cy, block_section in block_sections.items():
305
+ if floor_cy <= cy <= ceil_cy:
306
+ block_sub_array = numpy.transpose(block_section, (1, 2, 0)).ravel()
307
+ block_lut, block_arr = unique_inverse(block_sub_array)
308
+ palette_tag = ListTag[CompoundTag]()
309
+ for palette_index in block_lut:
310
+ palette_tag.append(
311
+ encode_block(
312
+ game_version,
313
+ block_palette.index_to_block_stack(palette_index),
314
+ )
315
+ )
316
+
317
+ section_tag = get_section(cy)
318
+ if data_version >= 2836:
319
+ section_tag["block_states"] = block_states_tag = CompoundTag(
320
+ {"palette": palette_tag}
321
+ )
322
+ if len(palette_tag) > 1:
323
+ block_states_tag["data"] = LongArrayTag(
324
+ encode_long_array(
325
+ block_sub_array,
326
+ dense=data_version <= 2529,
327
+ min_bits_per_entry=4,
328
+ )
329
+ )
330
+ else:
331
+ section_tag["Palette"] = palette_tag
332
+ section_tag["BlockStates"] = LongArrayTag(
333
+ encode_long_array(
334
+ block_sub_array,
335
+ dense=data_version <= 2529,
336
+ min_bits_per_entry=4,
337
+ )
338
+ )
339
+ else:
340
+ # region.Level.Sections[].Blocks
341
+ # region.Level.Sections[].Add
342
+ # region.Level.Sections[].Data
343
+ get_block_id_override = raw_level.block_id_override.namespace_id_to_numerical_id
344
+ get_block_id_game = game_version.block.namespace_id_to_numerical_id
345
+ block_ids = []
346
+ block_datas = []
347
+ for block_stack in block_palette:
348
+ block = block_stack[0]
349
+ namespace = block.namespace
350
+ base_name = block.base_name
351
+ try:
352
+ block_id = get_block_id_override(namespace, base_name)
353
+ except KeyError:
354
+ try:
355
+ block_id = get_block_id_game(namespace, base_name)
356
+ except KeyError:
357
+ if namespace == "numerical" and base_name.isnumeric():
358
+ block_id = int(base_name) & 255
359
+ else:
360
+ block_id = 0
361
+
362
+ block_data_tag = block.properties.get("block_data")
363
+ if isinstance(block_data_tag, AbstractBaseIntTag):
364
+ block_data = block_data_tag.py_int & 15
365
+ else:
366
+ block_data = 0
367
+ block_ids.append(block_id)
368
+ block_datas.append(block_data)
369
+ block_id_array = numpy.array(block_ids, dtype=numpy.uint8)
370
+ block_data_array = numpy.array(block_datas, dtype=numpy.uint8)
371
+
372
+ for cy, block_section in block_sections.items():
373
+ if 0 <= cy <= 16:
374
+ flat_block_section = numpy.transpose(
375
+ block_section, (1, 2, 0)
376
+ ).ravel() # XYZ -> YZX
377
+ section_tag = get_section(cy)
378
+ section_tag["Blocks"] = ByteArrayTag(block_id_array[flat_block_section])
379
+ section_tag["Data"] = ByteArrayTag(
380
+ to_nibble_array(block_data_array[flat_block_section])
381
+ )
382
+
383
+ # block entities
384
+ block_entities = ListTag[CompoundTag]()
385
+ block_entity: BlockEntity
386
+ for (x, y, z), block_entity in chunk.get_component(BlockEntityComponent).items():
387
+ tag = block_entity.nbt.compound
388
+ tag["id"] = StringTag(block_entity.namespaced_name)
389
+ tag["x"] = IntTag(x)
390
+ tag["y"] = IntTag(y)
391
+ tag["z"] = IntTag(z)
392
+ block_entities.append(tag)
393
+ if data_version >= 2844:
394
+ # region.block_entities
395
+ region["block_entities"] = block_entities
396
+ else:
397
+ # region.Level.TileEntities
398
+ level["TileEntities"] = block_entities
399
+
400
+ # entities
401
+ entities = ListTag[CompoundTag]()
402
+ entity: Entity
403
+ for entity in chunk.get_component(EntityComponent):
404
+ tag = entity.nbt.compound
405
+ tag["id"] = StringTag(entity.namespaced_name)
406
+ tag["Pos"] = ListTag(
407
+ [DoubleTag(entity.x), DoubleTag(entity.y), DoubleTag(entity.z)]
408
+ )
409
+ entities.append(tag)
410
+ if data_version >= 2681:
411
+ # entities.Entities
412
+ entity_layer = raw_chunk.setdefault("entities", NamedTag()).compound
413
+ entity_layer["Entities"] = entities
414
+ else:
415
+ # region.Level.Entities
416
+ level["Entities"] = entities
417
+
418
+ if 1519 <= data_version < 1901:
419
+ # all defined sections must have the BlockStates and Palette fields
420
+ for section in sections_map.values():
421
+ if "Palette" in section:
422
+ if "BlockStates" not in section:
423
+ assert len(section.get_list("Palette", raise_errors=True)) == 1
424
+ section["BlockStates"] = LongArrayTag([0] * 256)
425
+ else:
426
+ section["Palette"] = ListTag(
427
+ [CompoundTag({"Name": StringTag("minecraft:air")})]
428
+ )
429
+ section["BlockStates"] = LongArrayTag([0] * 256)
430
+
431
+ if data_version < 1934:
432
+ # BlockLight and SkyLight are required
433
+ for section_tag in sections_map.values():
434
+ for key in ("BlockLight", "SkyLight"):
435
+ if key not in section_tag:
436
+ section_tag[key] = ByteArrayTag(
437
+ numpy.full(2048, 255, dtype=numpy.uint8)
438
+ )
439
+
440
+ return raw_chunk
441
+
442
+
443
+ def encode_block(game_version: JavaGameVersion, block_stack: BlockStack) -> CompoundTag:
444
+ base_block = block_stack[0]
445
+ namespace = base_block.namespace
446
+ base_name = base_block.base_name
447
+ properties = dict(base_block.properties)
448
+ block_tag = CompoundTag({"Name": StringTag(f"{namespace}:{base_name}")})
449
+ if game_version.block.waterloggable(namespace, base_name) == Waterloggable.Yes:
450
+ if (
451
+ len(block_stack) >= 2
452
+ and block_stack[1].namespaced_name == "minecraft:water"
453
+ ):
454
+ properties["waterlogged"] = StringTag("true")
455
+ else:
456
+ properties["waterlogged"] = StringTag("false")
457
+ if properties:
458
+ string_properties = {
459
+ k: v for k, v in properties.items() if isinstance(v, StringTag)
460
+ }
461
+ if string_properties:
462
+ block_tag["Properties"] = CompoundTag(string_properties)
463
+ return block_tag
@@ -0,0 +1,9 @@
1
+ from amulet.selection import SelectionBox, SelectionGroup
2
+
3
+ OVERWORLD = "minecraft:overworld"
4
+ THE_NETHER = "minecraft:the_nether"
5
+ THE_END = "minecraft:the_end"
6
+
7
+ DefaultSelection = SelectionGroup(
8
+ SelectionBox((-30_000_000, 0, -30_000_000), (30_000_000, 256, 30_000_000))
9
+ )
@@ -0,0 +1,20 @@
1
+ from __future__ import annotations
2
+
3
+ import amulet.selection.group
4
+ from amulet.selection.box import SelectionBox
5
+ from amulet.selection.group import SelectionGroup
6
+
7
+ __all__ = [
8
+ "DefaultSelection",
9
+ "OVERWORLD",
10
+ "SelectionBox",
11
+ "SelectionGroup",
12
+ "THE_END",
13
+ "THE_NETHER",
14
+ ]
15
+ DefaultSelection: (
16
+ amulet.selection.group.SelectionGroup
17
+ ) # value = SelectionGroup([SelectionBox((-30000000, 0, -30000000), (30000000, 256, 30000000))])
18
+ OVERWORLD: str
19
+ THE_END: str
20
+ THE_NETHER: str
@@ -0,0 +1,2 @@
1
+ from .data_pack import DataPack
2
+ from .data_pack_manager import DataPackManager
@@ -0,0 +1,8 @@
1
+ from __future__ import annotations
2
+
3
+ from amulet.level.java._raw._data_pack.data_pack import DataPack
4
+ from amulet.level.java._raw._data_pack.data_pack_manager import DataPackManager
5
+
6
+ from . import data_pack, data_pack_manager
7
+
8
+ __all__ = ["DataPack", "DataPackManager", "data_pack", "data_pack_manager"]