amulet-core 2.0a5__cp312-cp312-win_amd64.whl → 2.0a7__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 (232) hide show
  1. amulet/__init__.cp312-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,602 +0,0 @@
1
- from __future__ import annotations
2
- import struct
3
- from typing import TYPE_CHECKING, Callable, Iterable
4
- from functools import cache
5
- from logging import getLogger
6
-
7
- import numpy
8
-
9
- from amulet_nbt import (
10
- CompoundTag,
11
- AbstractBaseIntTag,
12
- ShortTag,
13
- IntTag,
14
- FloatTag,
15
- StringTag,
16
- ListTag,
17
- NamedTag,
18
- utf8_escape_encoding,
19
- )
20
-
21
- from amulet.block import Block, PropertyValueType
22
- from amulet.block_entity import BlockEntity
23
- from amulet.entity import Entity
24
- from amulet.chunk.components.sub_chunk_array import SubChunkArrayContainer
25
- from amulet.chunk.components.block import BlockComponent, BlockComponentData
26
- from amulet.chunk.components.block_entity import (
27
- BlockEntityComponent,
28
- BlockEntityComponentData,
29
- )
30
- from amulet.chunk.components.entity import EntityComponent, EntityComponentData
31
- from amulet.chunk.components.height_2d import Height2DComponent
32
- from amulet.chunk.components.biome import Biome2DComponent, Biome3DComponent
33
- from amulet.game import get_game_version
34
- from amulet.version import VersionNumber
35
- from amulet.palette import BlockPalette, BiomePalette
36
- from amulet.utils.world_utils import to_nibble_array
37
- from amulet.utils.numpy import unique_inverse
38
-
39
- from amulet.level.bedrock._raw import BedrockRawChunk
40
- from amulet.level.bedrock.chunk import BedrockChunk
41
- from amulet.level.bedrock.chunk.components.finalised_state import (
42
- FinalisedStateComponent,
43
- )
44
- from amulet.level.bedrock.chunk.components.raw_chunk import RawChunkComponent
45
- from amulet.level.bedrock.chunk.components.chunk_version import ChunkVersionComponent
46
-
47
- if TYPE_CHECKING:
48
- from ._level import BedrockRawLevel
49
- from ._dimension import BedrockRawDimension
50
-
51
-
52
- log = getLogger(__name__)
53
-
54
-
55
- @cache
56
- def pack_block_version(version: VersionNumber) -> int:
57
- return struct.unpack(">i", bytes([*version.padded_version(4)]))[0] # type: ignore
58
-
59
-
60
- def native_to_raw(
61
- raw_level: BedrockRawLevel, dimension: BedrockRawDimension, chunk: BedrockChunk
62
- ) -> BedrockRawChunk:
63
- game_version = get_game_version("bedrock", raw_level.version)
64
- max_version = game_version.max_version
65
-
66
- floor_cy = dimension.bounds().min_y >> 4
67
- ceil_cy = dimension.bounds().max_y >> 4
68
-
69
- if chunk.has_component(RawChunkComponent):
70
- raw_chunk_component = chunk.get_component(RawChunkComponent)
71
- if raw_chunk_component is None:
72
- raw_chunk = BedrockRawChunk()
73
- else:
74
- raw_chunk = raw_chunk_component
75
- else:
76
- raw_chunk = BedrockRawChunk()
77
-
78
- chunk_data = raw_chunk.chunk_data
79
-
80
- # Chunk version
81
- chunk_version = chunk.get_component(ChunkVersionComponent)
82
- chunk_data[b"v" if chunk_version <= 20 else b","] = bytes([chunk_version])
83
-
84
- # Finalised state
85
- finalised_state = chunk.get_component(FinalisedStateComponent)
86
- if max_version >= VersionNumber(1):
87
- # TODO: when did this become an int?
88
- chunk_data[b"\x36"] = struct.pack("<i", finalised_state)
89
- else:
90
- chunk_data[b"\x36"] = struct.pack("b", finalised_state)
91
-
92
- # blocks
93
- block_component = chunk.get_component(BlockComponent)
94
- terrain: dict[int, bytes]
95
- if max_version >= VersionNumber(1, 17, 30):
96
- terrain = _encode_blocks_v9(
97
- block_component, floor_cy, ceil_cy, dimension.default_block()[0]
98
- )
99
- elif max_version >= VersionNumber(1, 3):
100
- terrain = _encode_blocks_v8(
101
- block_component, floor_cy, ceil_cy, dimension.default_block()[0]
102
- )
103
- elif max_version >= VersionNumber(0, 17):
104
- terrain = _encode_blocks_v1(block_component, dimension.default_block()[0])
105
- else:
106
- get_block_id_override = raw_level.block_id_override.namespace_id_to_numerical_id
107
- get_block_id_game = game_version.block.namespace_id_to_numerical_id
108
-
109
- @cache
110
- def encode_block(block: Block) -> tuple[int, int]:
111
- namespace = block.namespace
112
- base_name = block.base_name
113
- try:
114
- block_id = get_block_id_override(namespace, base_name)
115
- except KeyError:
116
- try:
117
- block_id = get_block_id_game(namespace, base_name)
118
- except KeyError:
119
- if namespace == "numerical" and base_name.isnumeric():
120
- block_id = int(base_name) & 255
121
- else:
122
- return 0, 0
123
- block_data_tag = block.properties.get("block_data")
124
- if isinstance(block_data_tag, AbstractBaseIntTag):
125
- block_data = block_data_tag.py_int & 15
126
- else:
127
- block_data = 0
128
- return block_id, block_data
129
-
130
- terrain = _encode_blocks_v0(block_component, encode_block)
131
-
132
- # TODO: is this right?
133
- for cy, sub_chunk in terrain.items():
134
- if 25 <= chunk_version <= 28:
135
- # The chunk db keys all start at 0 regardless of chunk floor position.
136
- # This is the floor position of when the world was created.
137
- # If the floor position changes in the future this will break.
138
- chunk_key = struct.pack("b", cy - floor_cy)
139
- else:
140
- chunk_key = struct.pack("b", cy)
141
-
142
- chunk_data[b"\x2F" + chunk_key] = sub_chunk
143
-
144
- block_entity_component = chunk.get_component(BlockEntityComponent)
145
- block_entities_out = _encode_block_entities(block_entity_component)
146
- if block_entities_out:
147
- chunk_data[b"\x31"] = _pack_nbt_list(block_entities_out)
148
-
149
- entity_component = chunk.get_component(EntityComponent)
150
- entities_out = _encode_entities(
151
- entity_component, max_version >= VersionNumber(1, 8)
152
- )
153
- if entities_out:
154
- if max_version >= VersionNumber(1, 18, 30):
155
- raw_chunk.entity_actor.extend(entities_out)
156
- else:
157
- chunk_data[b"\x32"] = _pack_nbt_list(entities_out)
158
-
159
- height_component = chunk.get_component(Height2DComponent)
160
- if height_component is None:
161
- height = bytes(512)
162
- else:
163
- height = height_component.ravel().astype("<i2").tobytes()
164
-
165
- get_biome_id_override = raw_level.biome_id_override.namespace_id_to_numerical_id
166
- get_biome_id_game = game_version.biome.namespace_id_to_numerical_id
167
-
168
- @cache
169
- def encode_biome(namespace: str, base_name: str) -> int:
170
- try:
171
- # First try overrides
172
- return get_biome_id_override(namespace, base_name)
173
- except KeyError:
174
- try:
175
- # Then fall back to the game implementation.
176
- return get_biome_id_game(namespace, base_name)
177
- except KeyError:
178
- log.error(
179
- f"Unknown biome {namespace}:{base_name}. Falling back to default."
180
- )
181
- default_biome = dimension.default_biome()
182
- if (
183
- namespace == default_biome.namespace
184
- and base_name == default_biome.base_name
185
- ):
186
- return 0
187
- return encode_biome(default_biome.namespace, default_biome.base_name)
188
-
189
- if chunk.has_component(Biome2DComponent):
190
- biome_2d_component = chunk.get_component(Biome2DComponent)
191
- palette_indexes, array = numpy.unique(
192
- biome_2d_component.array, return_inverse=True
193
- )
194
-
195
- biome_id_palette = _encode_biome_palette(
196
- biome_2d_component.palette,
197
- palette_indexes,
198
- encode_biome,
199
- )
200
-
201
- biomes_array = numpy.asarray(biome_id_palette, dtype=numpy.uint8)[
202
- array
203
- ].T.tobytes()
204
- chunk_data[b"\x2D"] = height + biomes_array
205
-
206
- elif chunk.has_component(Biome3DComponent):
207
- biome_3d_component = chunk.get_component(Biome3DComponent)
208
- d2d: list[bytes] = [height]
209
-
210
- biomes: SubChunkArrayContainer = biome_3d_component.sections
211
- biome_palette = biome_3d_component.palette
212
-
213
- def encode_biome_section(array: numpy.ndarray) -> bytes:
214
- palette_indexes, arr_uniq = numpy.unique(array, return_inverse=True)
215
-
216
- biome_id_palette = _encode_biome_palette(
217
- biome_palette,
218
- palette_indexes,
219
- encode_biome,
220
- )
221
-
222
- if len(biome_id_palette) == 1:
223
- encoded_section = b"\x01"
224
- else:
225
- encoded_section = _encode_packed_array(
226
- arr_uniq.reshape(array.shape)
227
- ) + struct.pack("<I", len(biome_id_palette))
228
- return (
229
- encoded_section
230
- + numpy.asarray(biome_id_palette, dtype=numpy.uint32).tobytes()
231
- )
232
-
233
- @cache
234
- def get_default_biome_section() -> bytes:
235
- default_section = biomes.default_array
236
- if isinstance(default_section, int):
237
- default_section = numpy.full(
238
- (16, 16, 16), default_section, dtype=numpy.uint32
239
- )
240
- return encode_biome_section(default_section)
241
-
242
- highest_cy = next(
243
- (cy for cy in range(ceil_cy, floor_cy - 1, -1) if cy in biomes), floor_cy
244
- )
245
-
246
- for cy in range(floor_cy, floor_cy + 25):
247
- if cy in biomes:
248
- d2d.append(encode_biome_section(biomes[cy]))
249
- elif cy <= highest_cy:
250
- # Everything below the highest must be defined
251
- d2d.append(get_default_biome_section())
252
- else:
253
- d2d.append(b"\xFF")
254
-
255
- chunk_data[b"+"] = b"".join(d2d)
256
- else:
257
- raise RuntimeError
258
-
259
- return raw_chunk
260
-
261
-
262
- def _encode_biome_palette(
263
- biome_palette: BiomePalette,
264
- palette_indexes: Iterable[int],
265
- encode_biome: Callable[[str, str], int],
266
- ) -> list[int]:
267
- biome_int_palette: list[int] = []
268
- for palette_index in palette_indexes:
269
- biome = biome_palette[palette_index]
270
- biome_int_palette.append(encode_biome(biome.namespace, biome.base_name))
271
- return biome_int_palette
272
-
273
-
274
- def _encode_blocks_v0(
275
- block_component: BlockComponentData,
276
- encode_block: Callable[[Block], tuple[int, int]],
277
- ) -> dict[int, bytes]:
278
- blocks: SubChunkArrayContainer = block_component.sections
279
- block_palette = block_component.palette
280
- sections: dict[int, bytes] = {}
281
-
282
- palette = numpy.array(
283
- [encode_block(block_stack[0]) for block_stack in block_palette]
284
- )
285
- for cy in range(16):
286
- if cy in blocks:
287
- block_sub_array = palette[numpy.transpose(blocks[cy], (0, 2, 1)).ravel()]
288
- if numpy.any(block_sub_array):
289
- data_sub_array = block_sub_array[:, 1]
290
- block_sub_array = block_sub_array[:, 0]
291
- sections[cy] = (
292
- b"\00"
293
- + block_sub_array.astype("uint8").tobytes()
294
- + to_nibble_array(data_sub_array).tobytes()
295
- )
296
-
297
- return sections
298
-
299
-
300
- @cache
301
- def _encode_block(block: Block) -> NamedTag:
302
- """Encode a block to its NameTag form.
303
-
304
- Note that this may return a cached result. Do not modify the returned value.
305
-
306
- :param block: The block to encode
307
- :return: The encoded block.
308
- """
309
- if block.version >= VersionNumber(1, 13): # This version may be wrong
310
- # block with block state
311
- return NamedTag(
312
- CompoundTag(
313
- {
314
- "name": StringTag(block.namespaced_name),
315
- "states": CompoundTag(
316
- {
317
- key: val
318
- for key, val in block.properties.items()
319
- if isinstance(val, PropertyValueType)
320
- }
321
- ),
322
- "version": IntTag(pack_block_version(block.version)),
323
- }
324
- )
325
- )
326
- else:
327
- # block with block data
328
- block_data = block.properties.get("block_data", IntTag(0))
329
- if isinstance(block_data, IntTag):
330
- block_data_int = block_data.py_int
331
- else:
332
- block_data_int = 0
333
- return NamedTag(
334
- CompoundTag(
335
- {
336
- "name": StringTag(block.namespaced_name),
337
- "val": ShortTag(block_data_int),
338
- }
339
- )
340
- )
341
-
342
-
343
- def _encode_block_palette(
344
- block_palette: BlockPalette, default_block: Block, max_block_depth: int
345
- ) -> list[tuple[list[NamedTag], numpy.ndarray]]:
346
- """Encode the block palette.
347
-
348
- Remove duplicates from each layer of the palette.
349
- Return the encoded block palette and a numpy index array to remap the old block array.
350
-
351
- :param block_palette: The block palette to encode.
352
- :param default_block: The default block to use in extra layers where the block stack is not long enough.
353
- :param max_block_depth: The maximum block depth to process.
354
- :return: The encoded block palette and numpy inverse array for each layer.
355
- """
356
- block: Block | None
357
-
358
- # Transpose the block palette
359
- block_layers: list[list[Block | None]] = [
360
- [None] * len(block_palette) for _ in range(max_block_depth)
361
- ]
362
- for block_index, block_stack in enumerate(block_palette):
363
- for block_layer, block in enumerate(block_stack):
364
- if block_layer < max_block_depth:
365
- block_layers[block_layer][block_index] = block
366
-
367
- # Crop layers without extra blocks
368
- block_layers = block_layers[
369
- : next(
370
- (
371
- i + 1
372
- for i in range(len(block_layers) - 1, 0, -1)
373
- if any(block_layers[i])
374
- ),
375
- 1,
376
- )
377
- ]
378
-
379
- compact_layers: list[tuple[list[NamedTag], numpy.ndarray]] = []
380
-
381
- for layer in block_layers:
382
- compact_palette_lut: dict[Block, int] = {}
383
- encoded_palette: list[NamedTag] = []
384
- remap: list[int] = []
385
- for block in layer:
386
- if block is None:
387
- block = default_block
388
- palette_index = compact_palette_lut.get(block)
389
- if palette_index is None:
390
- palette_index = len(compact_palette_lut)
391
- compact_palette_lut[block] = palette_index
392
- encoded_palette.append(_encode_block(block))
393
- remap.append(palette_index)
394
-
395
- compact_layers.append((encoded_palette, numpy.array(remap)))
396
-
397
- return compact_layers
398
-
399
-
400
- def _encode_block_palette_layer(
401
- layer_palette: list[NamedTag],
402
- layer_palette_lut: numpy.ndarray,
403
- palette_lut: numpy.ndarray,
404
- unique_block_array: numpy.ndarray,
405
- ) -> bytes:
406
- """Encode one palettised layer.
407
-
408
- The two look up tables are so that the unique can be computed once per sub-chunk rather than once per layer.
409
-
410
- :param layer_palette: The encoded block palette. This may contain unused values. All values must be unique.
411
- :param layer_palette_lut: A LUT mapping from the original block palette to the compacted palette for this layer.
412
- :param palette_lut: A LUT mapping from the unique block array to the original block palette.
413
- :param unique_block_array: The block array containing only unique values.
414
- :return: The encoded bytes
415
- """
416
- # merge the luts
417
- lut = layer_palette_lut[palette_lut]
418
- # compute the unique. This is faster than computing the unique for the whole array for each layer.
419
- palette_indexes, lut = numpy.unique(lut, return_inverse=True)
420
-
421
- unique_layer_palette = [layer_palette[i] for i in palette_indexes]
422
- block_array = lut[unique_block_array]
423
-
424
- return b"".join(
425
- (
426
- _encode_packed_array(block_array.reshape((16, 16, 16))),
427
- struct.pack("<I", len(unique_layer_palette)),
428
- *[
429
- block.save_to(
430
- compressed=False,
431
- little_endian=True,
432
- string_encoding=utf8_escape_encoding,
433
- )
434
- for block in unique_layer_palette
435
- ],
436
- )
437
- )
438
-
439
-
440
- def _encode_palettized_chunk(
441
- block_component: BlockComponentData,
442
- min_cy: int,
443
- max_cy: int,
444
- default_block: Block,
445
- max_block_depth: int,
446
- ) -> dict[int, list[bytes]]:
447
- """Encode the palettized sections of the chunk data. The caller handles the header."""
448
- blocks: SubChunkArrayContainer = block_component.sections
449
- block_palette: BlockPalette = block_component.palette
450
- encoded_block_palette = _encode_block_palette(
451
- block_palette, default_block, max_block_depth
452
- )
453
-
454
- encoded = {}
455
- for cy in range(min_cy, max_cy):
456
- if cy in blocks:
457
- block_lut, block_arr = unique_inverse(blocks[cy])
458
- encoded[cy] = [
459
- _encode_block_palette_layer(
460
- layer_palette, layer_palette_lut, block_lut, block_arr
461
- )
462
- for layer_palette, layer_palette_lut in encoded_block_palette
463
- ]
464
- return encoded
465
-
466
-
467
- def _encode_blocks_v1(
468
- block_component: BlockComponentData, default_block: Block
469
- ) -> dict[int, bytes]:
470
- return {
471
- cy: b"".join((b"\x01", *layers))
472
- for cy, layers in _encode_palettized_chunk(
473
- block_component, 0, 16, default_block, 1
474
- ).items()
475
- }
476
-
477
-
478
- def _encode_blocks_v8(
479
- block_component: BlockComponentData, min_cy: int, max_cy: int, default_block: Block
480
- ) -> dict[int, bytes]:
481
- return {
482
- cy: b"".join((b"\x08", struct.pack("b", len(layers)), *layers))
483
- for cy, layers in _encode_palettized_chunk(
484
- block_component, min_cy, max_cy, default_block, 2
485
- ).items()
486
- }
487
-
488
-
489
- def _encode_blocks_v9(
490
- block_component: BlockComponentData, min_cy: int, max_cy: int, default_block: Block
491
- ) -> dict[int, bytes]:
492
- return {
493
- cy: b"".join((b"\x09", struct.pack("bb", len(layers), cy), *layers))
494
- for cy, layers in _encode_palettized_chunk(
495
- block_component, min_cy, max_cy, default_block, 2
496
- ).items()
497
- }
498
-
499
-
500
- def _encode_packed_array(arr: numpy.ndarray, min_bit_size: int = 1) -> bytes:
501
- bits_per_value = max(int(numpy.amax(arr)).bit_length(), min_bit_size)
502
- if bits_per_value == 7:
503
- bits_per_value = 8
504
- elif 9 <= bits_per_value <= 15:
505
- bits_per_value = 16
506
- header = bytes([bits_per_value << 1])
507
-
508
- values_per_word = 32 // bits_per_value # Word = 4 bytes, basis of compacting.
509
- word_count = -(-4096 // values_per_word) # Ceiling divide is inverted floor divide
510
-
511
- arr = arr.swapaxes(1, 2).ravel()
512
- packed_arr = bytes(
513
- reversed(
514
- numpy.packbits(
515
- numpy.pad(
516
- numpy.pad(
517
- numpy.unpackbits(
518
- numpy.ascontiguousarray(arr[::-1], dtype=">i").view(
519
- dtype="uint8"
520
- )
521
- ).reshape(4096, -1)[:, -bits_per_value:],
522
- [(word_count * values_per_word - 4096, 0), (0, 0)],
523
- "constant",
524
- ).reshape(-1, values_per_word * bits_per_value),
525
- [(0, 0), (32 - values_per_word * bits_per_value, 0)],
526
- "constant",
527
- )
528
- )
529
- .view(dtype=">i4")
530
- .tobytes()
531
- )
532
- )
533
- return header + packed_arr
534
-
535
-
536
- def _pack_nbt_list(nbt_list: list[NamedTag]) -> bytes:
537
- return b"".join(
538
- [
539
- nbt.save_to(
540
- compressed=False,
541
- little_endian=True,
542
- string_encoding=utf8_escape_encoding,
543
- )
544
- for nbt in nbt_list
545
- ]
546
- )
547
-
548
-
549
- def _encode_entities(entities: EntityComponentData, str_id: bool) -> list[NamedTag]:
550
- entities_out = []
551
- for entity in entities:
552
- nbt = _encode_entity(entity, str_id)
553
- if nbt is not None:
554
- entities_out.append(nbt)
555
-
556
- return entities_out
557
-
558
-
559
- def _encode_entity(entity: Entity, str_id: bool) -> NamedTag | None:
560
- named_tag = entity.nbt
561
- tag = named_tag.tag
562
- if not isinstance(tag, CompoundTag):
563
- return None
564
-
565
- if entity.namespace == "numerical" and entity.base_name.isnumeric():
566
- tag["id"] = IntTag(int(entity.base_name))
567
- elif str_id:
568
- tag["identifier"] = StringTag(entity.namespaced_name)
569
- else:
570
- return None
571
-
572
- tag["Pos"] = ListTag(
573
- [
574
- FloatTag(float(entity.x)),
575
- FloatTag(float(entity.y)),
576
- FloatTag(float(entity.z)),
577
- ]
578
- )
579
- return named_tag
580
-
581
-
582
- def _encode_block_entities(block_entities: BlockEntityComponentData) -> list[NamedTag]:
583
- entities_out = []
584
- for location, block_entity in block_entities.items():
585
- nbt = _encode_block_entity(location, block_entity)
586
- if nbt is not None:
587
- entities_out.append(nbt)
588
- return entities_out
589
-
590
-
591
- def _encode_block_entity(
592
- location: tuple[int, int, int], block_entity: BlockEntity
593
- ) -> NamedTag | None:
594
- named_tag = block_entity.nbt
595
- tag = named_tag.tag
596
- if not isinstance(tag, CompoundTag):
597
- return None
598
- tag["id"] = StringTag(block_entity.base_name)
599
- tag["x"] = IntTag(location[0])
600
- tag["y"] = IntTag(location[1])
601
- tag["z"] = IntTag(location[2])
602
- return named_tag
@@ -1,9 +0,0 @@
1
- from amulet.selection import SelectionBox, SelectionGroup
2
-
3
- LOCAL_PLAYER = "~local_player"
4
- OVERWORLD = "minecraft:overworld"
5
- THE_NETHER = "minecraft:the_nether"
6
- THE_END = "minecraft:the_end"
7
- DefaultSelection = SelectionGroup(
8
- SelectionBox((-30_000_000, 0, -30_000_000), (30_000_000, 256, 30_000_000))
9
- )