amulet-core 2.0a5__cp311-cp311-win_amd64.whl → 2.0a7__cp311-cp311-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 (232) hide show
  1. amulet/__init__.cp311-win_amd64.pyd +0 -0
  2. amulet/__init__.py.cpp +43 -0
  3. amulet/__init__.pyi +0 -2
  4. amulet/_init.py +0 -2
  5. amulet/_version.py +3 -3
  6. amulet/biome.py.cpp +122 -0
  7. amulet/biome.pyi +0 -2
  8. amulet/block.py.cpp +377 -0
  9. amulet/block.pyi +0 -2
  10. amulet/block_entity.py.cpp +115 -0
  11. amulet/block_entity.pyi +0 -2
  12. amulet/chunk.py.cpp +80 -0
  13. amulet/chunk.pyi +0 -2
  14. amulet/chunk_components/biome_3d_component.cpp +5 -0
  15. amulet/chunk_components/biome_3d_component.hpp +79 -0
  16. amulet/chunk_components/block_component.cpp +41 -0
  17. amulet/chunk_components/block_component.hpp +88 -0
  18. amulet/chunk_components/block_entity_component.cpp +5 -0
  19. amulet/chunk_components/block_entity_component.hpp +147 -0
  20. amulet/chunk_components/section_array_map.cpp +129 -0
  21. amulet/chunk_components/section_array_map.hpp +147 -0
  22. amulet/chunk_components.pyi +20 -18
  23. amulet/collections/eq.py.hpp +37 -0
  24. amulet/collections/hash.py.hpp +27 -0
  25. amulet/collections/holder.py.hpp +37 -0
  26. amulet/collections/iterator.py.hpp +80 -0
  27. amulet/collections/mapping.py.hpp +199 -0
  28. amulet/collections/mutable_mapping.py.hpp +226 -0
  29. amulet/collections/sequence.py.hpp +163 -0
  30. amulet/collections.pyi +8 -5
  31. amulet/entity.py +22 -20
  32. amulet/game/translate/_functions/_code_functions/_text.py +2 -2
  33. amulet/game/translate/_functions/abc.py +10 -3
  34. amulet/img/__init__.py +10 -0
  35. amulet/img/missing_no.png +0 -0
  36. amulet/img/missing_pack.png +0 -0
  37. amulet/img/missing_world.png +0 -0
  38. amulet/io/binary_reader.hpp +45 -0
  39. amulet/io/binary_writer.hpp +30 -0
  40. amulet/level/__init__.pyi +2 -6
  41. amulet/level/abc/_level/_creatable_level.py +1 -2
  42. amulet/level/abc/_level/_level.py +1 -5
  43. amulet/level/java/__init__.pyi +0 -5
  44. amulet/level/java/_raw/__init__.pyi +0 -4
  45. amulet/level/java/_raw/java_chunk_decode.cpp +531 -0
  46. amulet/level/java/_raw/java_chunk_decode.hpp +23 -0
  47. amulet/level/java/_raw/java_chunk_encode.cpp +25 -0
  48. amulet/level/java/_raw/java_chunk_encode.hpp +23 -0
  49. amulet/level/java/chunk_components/data_version_component.cpp +32 -0
  50. amulet/level/java/chunk_components/data_version_component.hpp +31 -0
  51. amulet/level/java/chunk_components/java_raw_chunk_component.cpp +56 -0
  52. amulet/level/java/chunk_components/java_raw_chunk_component.hpp +45 -0
  53. amulet/level/java/java_chunk.cpp +170 -0
  54. amulet/level/java/java_chunk.hpp +141 -0
  55. amulet/level/java/long_array.hpp +175 -0
  56. amulet/level/java/long_array.pyi +2 -1
  57. amulet/mesh/block/__init__.py +1 -0
  58. amulet/mesh/block/block_mesh.py +369 -0
  59. amulet/mesh/block/cube.py +149 -0
  60. amulet/mesh/block/missing_block.py +20 -0
  61. amulet/mesh/util.py +17 -0
  62. amulet/palette/biome_palette.hpp +85 -0
  63. amulet/palette/block_palette.cpp +32 -0
  64. amulet/palette/block_palette.hpp +93 -0
  65. amulet/player.py +4 -6
  66. amulet/pybind11/collections.hpp +118 -0
  67. amulet/pybind11/numpy.hpp +26 -0
  68. amulet/pybind11/py_module.hpp +34 -0
  69. amulet/pybind11/type_hints.hpp +51 -0
  70. amulet/pybind11/types.hpp +25 -0
  71. amulet/pybind11/typing.hpp +7 -0
  72. amulet/resource_pack/__init__.py +62 -0
  73. amulet/resource_pack/abc/__init__.py +2 -0
  74. amulet/resource_pack/abc/resource_pack.py +38 -0
  75. amulet/resource_pack/abc/resource_pack_manager.py +87 -0
  76. amulet/resource_pack/bedrock/__init__.py +2 -0
  77. amulet/resource_pack/bedrock/bedrock_vanilla_fix/pack_icon.png +0 -0
  78. amulet/resource_pack/bedrock/bedrock_vanilla_fix/textures/blocks/grass_carried.png +0 -0
  79. amulet/resource_pack/bedrock/bedrock_vanilla_fix/textures/blocks/grass_side_carried.png +0 -0
  80. amulet/resource_pack/bedrock/bedrock_vanilla_fix/textures/blocks/water.png +0 -0
  81. amulet/resource_pack/bedrock/blockshapes/__init__.py +31 -0
  82. amulet/resource_pack/bedrock/blockshapes/air.py +35 -0
  83. amulet/resource_pack/bedrock/blockshapes/base_blockshape.py +29 -0
  84. amulet/resource_pack/bedrock/blockshapes/bubble_column.py +29 -0
  85. amulet/resource_pack/bedrock/blockshapes/cake.py +46 -0
  86. amulet/resource_pack/bedrock/blockshapes/chest.py +54 -0
  87. amulet/resource_pack/bedrock/blockshapes/comparator.py +51 -0
  88. amulet/resource_pack/bedrock/blockshapes/cross_texture.py +186 -0
  89. amulet/resource_pack/bedrock/blockshapes/cross_texture0.py +17 -0
  90. amulet/resource_pack/bedrock/blockshapes/cross_texture_green.py +16 -0
  91. amulet/resource_pack/bedrock/blockshapes/cube.py +38 -0
  92. amulet/resource_pack/bedrock/blockshapes/default.py +14 -0
  93. amulet/resource_pack/bedrock/blockshapes/door.py +38 -0
  94. amulet/resource_pack/bedrock/blockshapes/door1.py +14 -0
  95. amulet/resource_pack/bedrock/blockshapes/door2.py +14 -0
  96. amulet/resource_pack/bedrock/blockshapes/door3.py +14 -0
  97. amulet/resource_pack/bedrock/blockshapes/door4.py +14 -0
  98. amulet/resource_pack/bedrock/blockshapes/door5.py +14 -0
  99. amulet/resource_pack/bedrock/blockshapes/door6.py +14 -0
  100. amulet/resource_pack/bedrock/blockshapes/double_plant.py +40 -0
  101. amulet/resource_pack/bedrock/blockshapes/enchanting_table.py +22 -0
  102. amulet/resource_pack/bedrock/blockshapes/farmland.py +22 -0
  103. amulet/resource_pack/bedrock/blockshapes/fence.py +22 -0
  104. amulet/resource_pack/bedrock/blockshapes/flat.py +55 -0
  105. amulet/resource_pack/bedrock/blockshapes/flat_wall.py +55 -0
  106. amulet/resource_pack/bedrock/blockshapes/furnace.py +44 -0
  107. amulet/resource_pack/bedrock/blockshapes/furnace_lit.py +14 -0
  108. amulet/resource_pack/bedrock/blockshapes/green_cube.py +39 -0
  109. amulet/resource_pack/bedrock/blockshapes/ladder.py +36 -0
  110. amulet/resource_pack/bedrock/blockshapes/lilypad.py +14 -0
  111. amulet/resource_pack/bedrock/blockshapes/partial_block.py +57 -0
  112. amulet/resource_pack/bedrock/blockshapes/piston.py +44 -0
  113. amulet/resource_pack/bedrock/blockshapes/piston_arm.py +72 -0
  114. amulet/resource_pack/bedrock/blockshapes/portal_frame.py +22 -0
  115. amulet/resource_pack/bedrock/blockshapes/pressure_plate.py +29 -0
  116. amulet/resource_pack/bedrock/blockshapes/pumpkin.py +36 -0
  117. amulet/resource_pack/bedrock/blockshapes/pumpkin_carved.py +14 -0
  118. amulet/resource_pack/bedrock/blockshapes/pumpkin_lit.py +14 -0
  119. amulet/resource_pack/bedrock/blockshapes/red_dust.py +14 -0
  120. amulet/resource_pack/bedrock/blockshapes/repeater.py +53 -0
  121. amulet/resource_pack/bedrock/blockshapes/slab.py +33 -0
  122. amulet/resource_pack/bedrock/blockshapes/slab_double.py +15 -0
  123. amulet/resource_pack/bedrock/blockshapes/tree.py +41 -0
  124. amulet/resource_pack/bedrock/blockshapes/turtle_egg.py +15 -0
  125. amulet/resource_pack/bedrock/blockshapes/vine.py +52 -0
  126. amulet/resource_pack/bedrock/blockshapes/wall.py +22 -0
  127. amulet/resource_pack/bedrock/blockshapes/water.py +38 -0
  128. amulet/resource_pack/bedrock/download_resources.py +147 -0
  129. amulet/resource_pack/bedrock/resource_pack.py +40 -0
  130. amulet/resource_pack/bedrock/resource_pack_manager.py +361 -0
  131. amulet/resource_pack/bedrock/sort_blockshapes.py +15 -0
  132. amulet/resource_pack/java/__init__.py +2 -0
  133. amulet/resource_pack/java/download_resources.py +212 -0
  134. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_black.png +0 -0
  135. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_blue.png +0 -0
  136. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_brown.png +0 -0
  137. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_cyan.png +0 -0
  138. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_gray.png +0 -0
  139. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_green.png +0 -0
  140. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_light_blue.png +0 -0
  141. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_light_gray.png +0 -0
  142. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_lime.png +0 -0
  143. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_magenta.png +0 -0
  144. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_orange.png +0 -0
  145. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_pink.png +0 -0
  146. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_purple.png +0 -0
  147. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_red.png +0 -0
  148. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_white.png +0 -0
  149. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_yellow.png +0 -0
  150. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/barrier.png +0 -0
  151. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/end_portal.png +0 -0
  152. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/grass.png +0 -0
  153. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/lava.png +0 -0
  154. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/structure_void.png +0 -0
  155. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water.png +0 -0
  156. amulet/resource_pack/java/java_vanilla_fix/pack.png +0 -0
  157. amulet/resource_pack/java/resource_pack.py +44 -0
  158. amulet/resource_pack/java/resource_pack_manager.py +551 -0
  159. amulet/resource_pack/unknown_resource_pack.py +10 -0
  160. amulet/utils/__init__.pyi +0 -5
  161. amulet/utils/call_spec/_call_spec.py +2 -7
  162. amulet/utils/comment_json.py +188 -0
  163. amulet/utils/matrix.py +3 -3
  164. amulet/utils/numpy.hpp +36 -0
  165. amulet/utils/numpy_helpers.py +2 -2
  166. amulet/utils/world_utils.py +2 -2
  167. amulet/version.py.cpp +281 -0
  168. amulet/version.pyi +0 -8
  169. {amulet_core-2.0a5.dist-info → amulet_core-2.0a7.dist-info}/METADATA +3 -3
  170. amulet_core-2.0a7.dist-info/RECORD +295 -0
  171. amulet/chunk_/components/biome.py +0 -155
  172. amulet/chunk_/components/block_entity.py +0 -117
  173. amulet/chunk_/components/entity.py +0 -64
  174. amulet/chunk_/components/height_2d.py +0 -16
  175. amulet/level/bedrock/__init__.py +0 -2
  176. amulet/level/bedrock/_chunk_handle.py +0 -19
  177. amulet/level/bedrock/_dimension.py +0 -22
  178. amulet/level/bedrock/_level.py +0 -187
  179. amulet/level/bedrock/_raw/__init__.py +0 -5
  180. amulet/level/bedrock/_raw/_actor_counter.py +0 -53
  181. amulet/level/bedrock/_raw/_chunk.py +0 -54
  182. amulet/level/bedrock/_raw/_chunk_decode.py +0 -668
  183. amulet/level/bedrock/_raw/_chunk_encode.py +0 -602
  184. amulet/level/bedrock/_raw/_constant.py +0 -9
  185. amulet/level/bedrock/_raw/_dimension.py +0 -343
  186. amulet/level/bedrock/_raw/_level.py +0 -463
  187. amulet/level/bedrock/_raw/_level_dat.py +0 -90
  188. amulet/level/bedrock/_raw/_typing.py +0 -6
  189. amulet/level/bedrock/_raw/leveldb_chunk_versions.py +0 -83
  190. amulet/level/bedrock/chunk/__init__.py +0 -1
  191. amulet/level/bedrock/chunk/_chunk.py +0 -126
  192. amulet/level/bedrock/chunk/components/chunk_version.py +0 -12
  193. amulet/level/bedrock/chunk/components/finalised_state.py +0 -13
  194. amulet/level/bedrock/chunk/components/raw_chunk.py +0 -15
  195. amulet/level/construction/__init__.py +0 -0
  196. amulet/level/java/_chunk_handle.pyi +0 -15
  197. amulet/level/java/_dimension.pyi +0 -13
  198. amulet/level/java/_level.pyi +0 -120
  199. amulet/level/java/_raw/_chunk_decode.py +0 -561
  200. amulet/level/java/_raw/_chunk_encode.py +0 -463
  201. amulet/level/java/_raw/_constant.pyi +0 -20
  202. amulet/level/java/_raw/_data_pack/__init__.pyi +0 -8
  203. amulet/level/java/_raw/_data_pack/data_pack.pyi +0 -197
  204. amulet/level/java/_raw/_data_pack/data_pack_manager.pyi +0 -75
  205. amulet/level/java/_raw/_dimension.pyi +0 -72
  206. amulet/level/java/_raw/_level.pyi +0 -238
  207. amulet/level/java/_raw/_typing.pyi +0 -5
  208. amulet/level/java/anvil/__init__.pyi +0 -11
  209. amulet/level/java/anvil/_dimension.pyi +0 -109
  210. amulet/level/java/anvil/_region.pyi +0 -197
  211. amulet/level/java/anvil/_sector_manager.pyi +0 -142
  212. amulet/level/java_forge/__init__.py +0 -0
  213. amulet/level/mcstructure/__init__.py +0 -0
  214. amulet/level/nbt/__init__.py +0 -0
  215. amulet/level/schematic/__init__.py +0 -0
  216. amulet/level/sponge_schematic/__init__.py +0 -0
  217. amulet/utils/call_spec/__init__.pyi +0 -53
  218. amulet/utils/call_spec/_call_spec.pyi +0 -272
  219. amulet/utils/matrix.pyi +0 -177
  220. amulet/utils/shareable_lock.pyi +0 -190
  221. amulet/utils/signal/__init__.pyi +0 -25
  222. amulet/utils/signal/_signal.pyi +0 -84
  223. amulet/utils/task_manager.pyi +0 -168
  224. amulet/utils/typing.py +0 -4
  225. amulet/utils/typing.pyi +0 -6
  226. amulet/utils/weakref.pyi +0 -50
  227. amulet/utils/world_utils.pyi +0 -109
  228. amulet_core-2.0a5.dist-info/RECORD +0 -210
  229. /amulet/{level/bedrock/chunk/components → mesh}/__init__.py +0 -0
  230. {amulet_core-2.0a5.dist-info → amulet_core-2.0a7.dist-info}/WHEEL +0 -0
  231. {amulet_core-2.0a5.dist-info → amulet_core-2.0a7.dist-info}/entry_points.txt +0 -0
  232. {amulet_core-2.0a5.dist-info → amulet_core-2.0a7.dist-info}/top_level.txt +0 -0
@@ -1,668 +0,0 @@
1
- from __future__ import annotations
2
- import struct
3
- from typing import Optional, TypeVar, TYPE_CHECKING, Callable
4
- import logging
5
- from functools import cache
6
-
7
- import numpy
8
-
9
- from amulet_nbt import (
10
- CompoundTag,
11
- IntTag,
12
- FloatTag,
13
- StringTag,
14
- ListTag,
15
- NamedTag,
16
- ReadOffset,
17
- load_array as load_nbt_array,
18
- read_nbt,
19
- utf8_escape_encoding,
20
- )
21
-
22
- from amulet.block import Block, BlockStack, PropertyValueType
23
- from amulet.block_entity import BlockEntity
24
- from amulet.entity import Entity
25
- from amulet.biome import Biome
26
- from amulet.palette import BlockPalette
27
- from amulet.chunk import ComponentDataMapping
28
- from amulet.chunk.components.sub_chunk_array import SubChunkArrayContainer
29
- from amulet.chunk.components.block import BlockComponent, BlockComponentData
30
- from amulet.chunk.components.block_entity import (
31
- BlockEntityComponent,
32
- BlockEntityComponentData,
33
- )
34
- from amulet.chunk.components.entity import EntityComponent, EntityComponentData
35
- from amulet.chunk.components.height_2d import Height2DComponent
36
- from amulet.chunk.components.biome import (
37
- Biome2DComponent,
38
- Biome2DComponentData,
39
- Biome3DComponent,
40
- Biome3DComponentData,
41
- )
42
- from amulet.game import get_game_version
43
- from amulet.version import VersionNumber, VersionRange
44
-
45
- from amulet.utils.world_utils import from_nibble_array
46
- from amulet.utils.numpy import unique_inverse
47
-
48
- from amulet.level.bedrock._raw import BedrockRawChunk
49
- from amulet.level.bedrock.chunk import BedrockChunk, BedrockChunk0, BedrockChunk29
50
- from amulet.level.bedrock.chunk.components.finalised_state import (
51
- FinalisedStateComponent,
52
- )
53
- from amulet.level.bedrock.chunk.components.raw_chunk import RawChunkComponent
54
- from amulet.level.bedrock.chunk.components.chunk_version import ChunkVersionComponent
55
-
56
- if TYPE_CHECKING:
57
- from ._level import BedrockRawLevel
58
- from ._dimension import BedrockRawDimension
59
-
60
- log = logging.getLogger(__name__)
61
-
62
- SubChunkNDArray = numpy.ndarray
63
- AnyNDArray = numpy.ndarray
64
- T = TypeVar("T")
65
- GetT = TypeVar("GetT")
66
- SetT = TypeVar("SetT")
67
-
68
-
69
- @cache
70
- def unpack_block_version(block_version: int) -> VersionNumber:
71
- return VersionNumber(*struct.unpack("4B", struct.pack(">i", block_version)))
72
-
73
-
74
- def raw_to_native(
75
- raw_level: BedrockRawLevel,
76
- dimension: BedrockRawDimension,
77
- raw_chunk: BedrockRawChunk,
78
- ) -> BedrockChunk:
79
- game_version = get_game_version("bedrock", raw_level.version)
80
- max_version = game_version.max_version
81
-
82
- floor_cy = dimension.bounds().min_y >> 4
83
-
84
- chunk_data = raw_chunk.chunk_data
85
-
86
- # Get the chunk format version
87
- chunk_version_byte = chunk_data.pop(b",", None)
88
- if chunk_version_byte is None:
89
- chunk_version_byte = chunk_data.pop(b"v", None)
90
- if chunk_version_byte is None:
91
- raise RuntimeError
92
- chunk_version = chunk_version_byte[0]
93
-
94
- chunk_components: ComponentDataMapping = {} # type: ignore
95
- chunk_class: type[BedrockChunk]
96
- if chunk_version >= 29:
97
- chunk_class = BedrockChunk29
98
- else:
99
- chunk_class = BedrockChunk0
100
-
101
- version_range = VersionRange(
102
- "bedrock",
103
- VersionNumber(1, 0, 0),
104
- max_version,
105
- )
106
-
107
- chunk_components[RawChunkComponent] = raw_chunk
108
- chunk_components[ChunkVersionComponent] = chunk_version
109
-
110
- # Parse finalised state
111
- finalised_state = chunk_data.pop(b"\x36", None)
112
- if finalised_state is None:
113
- chunk_components[FinalisedStateComponent] = 2
114
- elif len(finalised_state) == 1:
115
- # old versions of the game store this as a byte
116
- chunk_components[FinalisedStateComponent] = struct.unpack("b", finalised_state)[
117
- 0
118
- ]
119
- elif len(finalised_state) == 4:
120
- # newer versions store it as an int
121
- chunk_components[FinalisedStateComponent] = struct.unpack(
122
- "<i", finalised_state
123
- )[0]
124
-
125
- # Parse blocks
126
- blocks: list[Block] = []
127
- for block in dimension.default_block():
128
- if version_range.contains(block.platform, block.version):
129
- blocks.append(block)
130
- else:
131
- block_ = get_game_version(block.platform, block.version).block.translate(
132
- "bedrock", max_version, block
133
- )[0]
134
- if isinstance(block_, Block):
135
- blocks.append(block_)
136
- chunk_components[BlockComponent] = block_component_data = BlockComponentData(
137
- version_range, (16, 16, 16), BlockStack(*blocks)
138
- )
139
- if chunk_version >= 3:
140
- subchunks = {}
141
- for key in chunk_data.copy().keys():
142
- if len(key) == 2 and key[0] == 0x2F:
143
- cy = struct.unpack("b", key[1:2])[0]
144
- if 25 <= chunk_version <= 28:
145
- cy += floor_cy
146
- subchunks[cy] = chunk_data.pop(key)
147
- _load_subchunks(raw_level, subchunks, block_component_data)
148
- else:
149
- section_data = chunk_data.pop(b"\x30", None)
150
- if section_data is not None:
151
- block_ids = numpy.frombuffer(
152
- section_data[: 2**15], dtype=numpy.uint8
153
- ).astype(numpy.uint32)
154
- block_data = from_nibble_array(
155
- numpy.frombuffer(section_data[2**15 : 2**15 + 2**14], dtype=numpy.uint8)
156
- )
157
-
158
- # there is other data here but we are going to skip over it
159
- combined_palette, block_array = unique_inverse(
160
- (block_ids << 4) + block_data
161
- )
162
- block_array = numpy.transpose(block_array.reshape(16, 16, 128), (0, 2, 1))
163
- block_component_data.sections = {
164
- i: block_array[:, i * 16 : (i + 1) * 16, :] for i in range(8)
165
- }
166
- palette: AnyNDArray = numpy.array(
167
- [combined_palette >> 4, combined_palette & 15]
168
- ).T
169
- chunk_palette = numpy.empty(len(palette), dtype=object)
170
- for i, b in enumerate(palette):
171
- chunk_palette[i] = ((None, tuple(b)),)
172
- raise NotImplementedError("Need to set up the block palette")
173
-
174
- # Parse block entities
175
- block_entity_component_data = BlockEntityComponentData(version_range)
176
- block_entities = _unpack_nbt_list(chunk_data.pop(b"\x31", b""))
177
- block_entity_component_data.update(_decode_block_entity_list(block_entities))
178
- chunk_components[BlockEntityComponent] = block_entity_component_data
179
-
180
- # Parse entities
181
- entity_component_data = EntityComponentData(version_range)
182
- entities = _unpack_nbt_list(chunk_data.pop(b"\x32", b""))
183
- entity_component_data |= set(
184
- _decode_entity_list(entities) + _decode_entity_list(raw_chunk.entity_actor)
185
- )
186
- raw_chunk.entity_actor.clear()
187
- chunk_components[EntityComponent] = entity_component_data
188
-
189
- # Parse biome and height data
190
- default_biome = dimension.default_biome()
191
- if not version_range.contains(default_biome.platform, default_biome.version):
192
- default_biome = get_game_version(
193
- default_biome.platform, default_biome.version
194
- ).biome.translate("bedrock", max_version, default_biome)
195
- if chunk_class.has_component(Biome3DComponent):
196
- chunk_components[Biome3DComponent] = biome_3d = Biome3DComponentData(
197
- version_range, (16, 16, 16), default_biome
198
- )
199
- if b"+" in chunk_data:
200
- d2d = chunk_data[b"+"]
201
- chunk_components[Height2DComponent] = (
202
- numpy.frombuffer(d2d[:512], "<i2").reshape((16, 16)).astype(numpy.int64)
203
- )
204
- _decode_3d_biomes(
205
- raw_level, biome_3d, d2d[512:], dimension.bounds().min_y >> 4
206
- )
207
- else:
208
- chunk_components[Height2DComponent] = numpy.zeros((16, 16), numpy.int64)
209
- elif chunk_class.has_component(Biome2DComponent):
210
- chunk_components[Biome2DComponent] = biome_2d = Biome2DComponentData(
211
- version_range, (16, 16), default_biome
212
- )
213
- if b"\x2D" in chunk_data:
214
- d2d = chunk_data[b"\x2D"]
215
- chunk_components[Height2DComponent] = (
216
- numpy.frombuffer(d2d[:512], "<i2").reshape((16, 16)).astype(numpy.int64)
217
- )
218
- _decode_2d_biomes(
219
- biome_2d,
220
- raw_level.version,
221
- numpy.frombuffer(d2d[512:], dtype="uint8"),
222
- raw_level.biome_id_override.numerical_id_to_namespace_id,
223
- game_version.biome.numerical_id_to_namespace_id,
224
- )
225
- else:
226
- chunk_components[Height2DComponent] = numpy.zeros((16, 16), numpy.int64)
227
- else:
228
- raise RuntimeError
229
-
230
- # TODO: implement key support
231
- # \x33 ticks
232
- # \x34 block extra data
233
- # \x35 biome state
234
- # \x39 7 ints and an end (03)? Honestly don't know what this is
235
- # \x3A fire tick?
236
-
237
- # \x2E 2d legacy
238
- # \x30 legacy terrain
239
-
240
- return chunk_class.from_component_data(chunk_components)
241
-
242
-
243
- def _load_palettized_subchunk(
244
- data: bytes,
245
- blocks: SubChunkArrayContainer,
246
- block_palette: BlockPalette,
247
- storage_count: int,
248
- cy: int,
249
- ) -> None:
250
- """Load a sub-chunk stored in the palettized format."""
251
- sub_chunk_blocks = numpy.zeros((16, 16, 16, storage_count), dtype=numpy.uint32)
252
- sub_chunk_palette: list[list[Block]] = []
253
- for storage_index in range(storage_count):
254
- (
255
- sub_chunk_blocks[:, :, :, storage_index],
256
- palette_data,
257
- data,
258
- ) = _load_palette_blocks(data)
259
- palette_data_out: list[Block] = []
260
- for block_nt in palette_data:
261
- block = block_nt.compound
262
- block_name = block.get_string("name")
263
- assert block_name is not None
264
- *namespace_, base_name = block_name.py_str.split(":", 1)
265
- namespace = namespace_[0] if namespace_ else "minecraft"
266
-
267
- properties: dict[str, PropertyValueType]
268
- if "states" in block:
269
- states = block.get_compound("states")
270
- assert states is not None
271
- properties = {
272
- k: v
273
- for k, v in states.items()
274
- if isinstance(k, str) and isinstance(v, PropertyValueType)
275
- }
276
- version = unpack_block_version(
277
- block.get_int("version", IntTag(17694720)).py_int
278
- )
279
- elif "val" in block:
280
- val = block.get_int("val")
281
- assert val is not None
282
- properties = {"block_data": IntTag(val.py_int)}
283
- version = VersionNumber(1, 12)
284
- else:
285
- properties = {}
286
- version = unpack_block_version(
287
- block.get_int("version", IntTag(17694720)).py_int
288
- )
289
-
290
- palette_data_out.append(
291
- Block(
292
- "bedrock",
293
- version,
294
- namespace=namespace,
295
- base_name=base_name,
296
- properties=properties,
297
- )
298
- )
299
- sub_chunk_palette.append(palette_data_out)
300
-
301
- if storage_count == 1:
302
- block_lut = [
303
- block_palette.block_stack_to_index(BlockStack(block))
304
- for block in sub_chunk_palette[0]
305
- ]
306
- blocks[cy] = numpy.array(block_lut, dtype=numpy.uint32)[
307
- sub_chunk_blocks[:, :, :, 0]
308
- ]
309
- elif storage_count > 1:
310
- # we have two or more storages so need to find the unique block combinations and merge them together
311
- sub_chunk_palette_, sub_chunk_blocks = numpy.unique(
312
- sub_chunk_blocks.reshape(-1, storage_count),
313
- return_inverse=True,
314
- axis=0,
315
- )
316
- block_lut = [
317
- block_palette.block_stack_to_index(
318
- BlockStack(
319
- *(
320
- sub_chunk_palette[storage_index][index]
321
- for storage_index, index in enumerate(palette_indexes)
322
- if storage_index == 0
323
- or sub_chunk_palette[storage_index][index].namespaced_name
324
- != "minecraft:air"
325
- )
326
- )
327
- )
328
- for palette_indexes in sub_chunk_palette_
329
- ]
330
- blocks[cy] = numpy.array(block_lut, dtype=numpy.uint32)[
331
- sub_chunk_blocks.reshape(16, 16, 16)
332
- ]
333
-
334
-
335
- def _load_binary_subchunk(
336
- data: bytes,
337
- level: BedrockRawLevel,
338
- blocks: SubChunkArrayContainer,
339
- block_palette: BlockPalette,
340
- cy: int,
341
- ) -> None:
342
- block_ids = numpy.frombuffer(data[: 2**12], dtype=numpy.uint8).astype(numpy.uint32)
343
- block_data = from_nibble_array(
344
- numpy.frombuffer(data[2**12 : 2**12 + 2**11], dtype=numpy.uint8)
345
- )
346
- numerical_palette, block_array = unique_inverse((block_ids << 4) + block_data)
347
- block_array = numpy.transpose(block_array.reshape(16, 16, 16), (0, 2, 1))
348
- block_lut: list[int] = []
349
- for block_id, block_data in numpy.array(
350
- [numerical_palette >> 4, numerical_palette & 15]
351
- ).T:
352
- try:
353
- (
354
- namespace,
355
- base_name,
356
- ) = level.block_id_override.numerical_id_to_namespace_id(block_id)
357
- except KeyError:
358
- try:
359
- namespace, base_name = get_game_version(
360
- "bedrock", level.version
361
- ).block.numerical_id_to_namespace_id(block_id)
362
- except KeyError:
363
- namespace = "numerical"
364
- base_name = str(block_id)
365
-
366
- block_lut.append(
367
- block_palette.block_stack_to_index(
368
- BlockStack(
369
- Block(
370
- "bedrock",
371
- VersionNumber(1, 12),
372
- namespace=namespace,
373
- base_name=base_name,
374
- properties={"block_data": IntTag(block_data)},
375
- )
376
- )
377
- )
378
- )
379
-
380
- blocks[cy] = numpy.array(block_lut, dtype=numpy.uint32)[block_array]
381
-
382
-
383
- def _load_subchunks(
384
- level: BedrockRawLevel, subchunks: dict[int, bytes], block_data: BlockComponentData
385
- ) -> None:
386
- """
387
- Load a list of bytes objects which contain chunk data into the chunk.
388
- This function should be able to load all sub-chunk formats (technically before it)
389
- All sub-chunks will almost certainly all have the same sub-chunk version but
390
- it should be able to handle a case where that is not true.
391
-
392
- The newer formats allow multiple blocks to occupy the same space and the
393
- newer versions also include a version ber block.
394
- """
395
- blocks: SubChunkArrayContainer = block_data.sections
396
- block_palette: BlockPalette = block_data.palette
397
- for cy, data in subchunks.items():
398
- sub_chunk_version, data = data[0], data[1:]
399
-
400
- if sub_chunk_version == 9:
401
- # There is an extra byte in this format storing the cy value
402
- storage_count, cy, data = (
403
- data[0],
404
- struct.unpack("b", data[1:2])[0],
405
- data[2:],
406
- )
407
- _load_palettized_subchunk(data, blocks, block_palette, storage_count, cy)
408
-
409
- elif sub_chunk_version == 8:
410
- storage_count, data = data[0], data[1:]
411
- _load_palettized_subchunk(data, blocks, block_palette, storage_count, cy)
412
-
413
- elif sub_chunk_version == 1:
414
- _load_palettized_subchunk(data, blocks, block_palette, 1, cy)
415
-
416
- elif 0 <= sub_chunk_version <= 7:
417
- _load_binary_subchunk(data, level, blocks, block_palette, cy)
418
- else:
419
- raise Exception(f"sub-chunk version {sub_chunk_version} is not known.")
420
-
421
-
422
- def _load_palette_blocks(
423
- data: bytes,
424
- ) -> tuple[numpy.ndarray, list[NamedTag], bytes]:
425
- data, _, blocks = _decode_packed_array(data)
426
- if blocks is None:
427
- blocks = numpy.zeros((16, 16, 16), dtype=numpy.int16)
428
- palette_len = 1
429
- else:
430
- palette_len, data = struct.unpack("<I", data[:4])[0], data[4:]
431
-
432
- if palette_len:
433
- read_offset = ReadOffset()
434
- palette = load_nbt_array(
435
- data,
436
- compressed=False,
437
- count=palette_len,
438
- little_endian=True,
439
- read_offset=read_offset,
440
- string_encoding=utf8_escape_encoding,
441
- )
442
- data = data[read_offset.offset :]
443
- else:
444
- palette = [
445
- NamedTag(
446
- CompoundTag(
447
- {
448
- "name": StringTag("minecraft:air"),
449
- "states": CompoundTag(),
450
- "version": IntTag(17694723),
451
- }
452
- )
453
- )
454
- ]
455
-
456
- return blocks, palette, data
457
-
458
-
459
- def _decode_2d_biomes(
460
- biome_2d_data: Biome2DComponentData,
461
- version: VersionNumber,
462
- arr: numpy.ndarray,
463
- numerical_id_to_namespace_id_override: Callable[[int], tuple[str, str]],
464
- numerical_id_to_namespace_id: Callable[[int], tuple[str, str]],
465
- ) -> None:
466
- numerical_ids, arr = numpy.unique(arr, return_inverse=True)
467
- arr = arr.reshape(16, 16).T.astype(numpy.uint32)
468
- lut = []
469
- for numerical_id in numerical_ids:
470
- try:
471
- (
472
- namespace,
473
- base_name,
474
- ) = numerical_id_to_namespace_id_override(numerical_id)
475
- except KeyError:
476
- namespace, base_name = numerical_id_to_namespace_id(numerical_id)
477
- biome = Biome("bedrock", version, namespace, base_name)
478
- runtime_id = biome_2d_data.palette.biome_to_index(biome)
479
- lut.append(runtime_id)
480
- biome_2d_data.array[:, :] = numpy.array(lut, dtype=numpy.uint32)[arr]
481
-
482
-
483
- def _decode_3d_biomes(
484
- raw_level: BedrockRawLevel,
485
- biome_3d_data: Biome3DComponentData,
486
- data: bytes,
487
- floor_cy: int,
488
- ) -> None:
489
- # TODO: how does Bedrock store custom biomes?
490
- # TODO: can I use one global lookup based on the max version or does it need to be done for the version the chunk was saved in?
491
-
492
- # The 3D biome format consists of 25 16x arrays with the first array corresponding to the lowest sub-chunk in the world
493
- # This is -64 in the overworld and 0 in the nether and end
494
- cy = floor_cy
495
- game_version = get_game_version("bedrock", raw_level.version)
496
- while data:
497
- data, bits_per_value, arr = _decode_packed_array(data)
498
- if bits_per_value == 0:
499
- numerical_id = struct.unpack(f"<I", data[:4])[0]
500
- try:
501
- (
502
- namespace,
503
- base_name,
504
- ) = raw_level.biome_id_override.numerical_id_to_namespace_id(
505
- numerical_id
506
- )
507
- except KeyError:
508
- namespace, base_name = game_version.biome.numerical_id_to_namespace_id(
509
- numerical_id
510
- )
511
- # TODO: should this be based on the chunk version?
512
- runtime_id = biome_3d_data.palette.biome_to_index(
513
- Biome("bedrock", raw_level.version, namespace, base_name)
514
- )
515
- biome_3d_data.sections[cy] = numpy.full(
516
- (16, 16, 16), runtime_id, dtype=numpy.uint32
517
- )
518
- data = data[4:]
519
- elif bits_per_value > 0:
520
- palette_len, data = struct.unpack("<I", data[:4])[0], data[4:]
521
- numerical_palette = numpy.frombuffer(data, "<i4", palette_len)
522
- lut = []
523
- for numerical_id in numerical_palette:
524
- try:
525
- (
526
- namespace,
527
- base_name,
528
- ) = raw_level.biome_id_override.numerical_id_to_namespace_id(
529
- numerical_id
530
- )
531
- except KeyError:
532
- namespace, base_name = (
533
- game_version.biome.numerical_id_to_namespace_id(numerical_id)
534
- )
535
- # TODO: should this be based on the chunk version?
536
- runtime_id = biome_3d_data.palette.biome_to_index(
537
- Biome("bedrock", raw_level.version, namespace, base_name)
538
- )
539
- lut.append(runtime_id)
540
- biome_3d_data.sections[cy] = numpy.array(lut, dtype=numpy.uint32)[arr]
541
- data = data[4 * palette_len :]
542
- cy += 1
543
-
544
-
545
- def _decode_packed_array(data: bytes) -> tuple[bytes, int, Optional[numpy.ndarray]]:
546
- """
547
- Parse a packed array as documented here
548
- https://gist.github.com/Tomcc/a96af509e275b1af483b25c543cfbf37
549
-
550
- :param data: The data to parse
551
- :return:
552
- """
553
- # Ignore LSB of data (it is a flag) and get compacting level
554
- bits_per_value, data = struct.unpack("b", data[0:1])[0] >> 1, data[1:]
555
- if bits_per_value > 0:
556
- values_per_word = 32 // bits_per_value # Word = 4 bytes, basis of compacting.
557
- word_count = -(
558
- -4096 // values_per_word
559
- ) # Ceiling divide is inverted floor divide
560
-
561
- arr = numpy.packbits(
562
- numpy.pad(
563
- numpy.unpackbits(
564
- numpy.frombuffer(
565
- bytes(reversed(data[: 4 * word_count])), dtype="uint8"
566
- )
567
- )
568
- .reshape(-1, 32)[:, -values_per_word * bits_per_value :]
569
- .reshape(-1, bits_per_value)[-4096:, :],
570
- [(0, 0), (16 - bits_per_value, 0)],
571
- "constant",
572
- )
573
- ).view(dtype=">i2")[::-1]
574
- arr = arr.reshape((16, 16, 16)).swapaxes(1, 2)
575
- data = data[4 * word_count :]
576
- else:
577
- arr = None
578
- return data, bits_per_value, arr
579
-
580
-
581
- def _unpack_nbt_list(raw_nbt: bytes) -> list[NamedTag]:
582
- nbt_list = []
583
- while raw_nbt:
584
- read_offset = ReadOffset()
585
- nbt = read_nbt(
586
- raw_nbt,
587
- little_endian=True,
588
- read_offset=read_offset,
589
- string_encoding=utf8_escape_encoding,
590
- )
591
- raw_nbt = raw_nbt[read_offset.offset :]
592
- nbt_list.append(nbt)
593
- return nbt_list
594
-
595
-
596
- def pop_nbt(tag: CompoundTag, key: str, dtype: type[T]) -> T:
597
- value = tag.pop(key)
598
- if not isinstance(value, dtype):
599
- raise TypeError
600
- return value
601
-
602
-
603
- def _decode_block_entity_list(
604
- block_entities: list[NamedTag],
605
- ) -> list[tuple[tuple[int, int, int], BlockEntity]]:
606
- return [ent for ent in map(_decode_block_entity, block_entities) if ent is not None]
607
-
608
-
609
- def _decode_block_entity(
610
- nbt: NamedTag,
611
- ) -> Optional[tuple[tuple[int, int, int], BlockEntity]]:
612
- try:
613
- tag = nbt.compound
614
- namespace = ""
615
- base_name = pop_nbt(tag, "id", StringTag).py_str
616
- if not base_name:
617
- raise Exception("entity id is empty")
618
- x = pop_nbt(tag, "x", IntTag).py_int
619
- y = pop_nbt(tag, "y", IntTag).py_int
620
- z = pop_nbt(tag, "z", IntTag).py_int
621
- return (x, y, z), BlockEntity(
622
- platform="bedrock",
623
- version=VersionNumber(1, 0, 0),
624
- namespace=namespace,
625
- base_name=base_name,
626
- nbt=nbt,
627
- )
628
- except Exception as e:
629
- log.exception(e)
630
- return None
631
-
632
-
633
- def _decode_entity_list(entities: list[NamedTag]) -> list[Entity]:
634
- return [ent for ent in map(_decode_entity, entities) if ent is not None]
635
-
636
-
637
- def _decode_entity(
638
- nbt: NamedTag,
639
- ) -> Optional[Entity]:
640
- try:
641
- tag = nbt.compound
642
- if "identifier" in tag:
643
- namespace, base_name = pop_nbt(tag, "identifier", StringTag).py_str.split(
644
- ":", 1
645
- )
646
- elif "id" in tag:
647
- # TODO: we should probably look up the real entity id
648
- namespace = "numerical"
649
- base_name = str(pop_nbt(tag, "id", IntTag).py_int)
650
- else:
651
- raise Exception("tag does not have identifier or id keys.")
652
-
653
- pos = pop_nbt(tag, "Pos", ListTag)
654
- x, y, z = (v.py_float for v in pos if isinstance(v, FloatTag))
655
-
656
- return Entity(
657
- platform="bedrock",
658
- version=VersionNumber(1, 0, 0),
659
- namespace=namespace,
660
- base_name=base_name,
661
- x=x,
662
- y=y,
663
- z=z,
664
- nbt=nbt,
665
- )
666
- except Exception as e:
667
- log.error(e)
668
- return None