amulet-core 2.0a5__cp312-cp312-macosx_10_13_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of amulet-core might be problematic. Click here for more details.
- amulet/__init__.cpython-312-darwin.so +0 -0
- amulet/__init__.pyi +30 -0
- amulet/__pyinstaller/__init__.py +2 -0
- amulet/__pyinstaller/hook-amulet.py +4 -0
- amulet/_init.py +28 -0
- amulet/_version.py +21 -0
- amulet/biome.cpp +36 -0
- amulet/biome.hpp +43 -0
- amulet/biome.pyi +77 -0
- amulet/block.cpp +435 -0
- amulet/block.hpp +119 -0
- amulet/block.pyi +273 -0
- amulet/block_entity.cpp +12 -0
- amulet/block_entity.hpp +56 -0
- amulet/block_entity.pyi +80 -0
- amulet/chunk.cpp +16 -0
- amulet/chunk.hpp +99 -0
- amulet/chunk.pyi +30 -0
- amulet/chunk_/components/biome.py +155 -0
- amulet/chunk_/components/block_entity.py +117 -0
- amulet/chunk_/components/entity.py +64 -0
- amulet/chunk_/components/height_2d.py +16 -0
- amulet/chunk_components.pyi +95 -0
- amulet/collections.pyi +37 -0
- amulet/data_types.py +29 -0
- amulet/entity.py +180 -0
- amulet/errors.py +63 -0
- amulet/game/__init__.py +7 -0
- amulet/game/_game.py +152 -0
- amulet/game/_universal/__init__.py +1 -0
- amulet/game/_universal/_biome.py +17 -0
- amulet/game/_universal/_block.py +47 -0
- amulet/game/_universal/_version.py +68 -0
- amulet/game/abc/__init__.py +22 -0
- amulet/game/abc/_block_specification.py +150 -0
- amulet/game/abc/biome.py +213 -0
- amulet/game/abc/block.py +331 -0
- amulet/game/abc/game_version_container.py +25 -0
- amulet/game/abc/json_interface.py +27 -0
- amulet/game/abc/version.py +44 -0
- amulet/game/bedrock/__init__.py +1 -0
- amulet/game/bedrock/_biome.py +35 -0
- amulet/game/bedrock/_block.py +42 -0
- amulet/game/bedrock/_version.py +165 -0
- amulet/game/java/__init__.py +2 -0
- amulet/game/java/_biome.py +35 -0
- amulet/game/java/_block.py +60 -0
- amulet/game/java/_version.py +176 -0
- amulet/game/translate/__init__.py +12 -0
- amulet/game/translate/_functions/__init__.py +15 -0
- amulet/game/translate/_functions/_code_functions/__init__.py +0 -0
- amulet/game/translate/_functions/_code_functions/_text.py +553 -0
- amulet/game/translate/_functions/_code_functions/banner_pattern.py +67 -0
- amulet/game/translate/_functions/_code_functions/bedrock_chest_connection.py +152 -0
- amulet/game/translate/_functions/_code_functions/bedrock_moving_block_pos.py +88 -0
- amulet/game/translate/_functions/_code_functions/bedrock_sign.py +152 -0
- amulet/game/translate/_functions/_code_functions/bedrock_skull_rotation.py +16 -0
- amulet/game/translate/_functions/_code_functions/custom_name.py +146 -0
- amulet/game/translate/_functions/_frozen.py +66 -0
- amulet/game/translate/_functions/_state.py +54 -0
- amulet/game/translate/_functions/_typing.py +98 -0
- amulet/game/translate/_functions/abc.py +116 -0
- amulet/game/translate/_functions/carry_nbt.py +160 -0
- amulet/game/translate/_functions/carry_properties.py +80 -0
- amulet/game/translate/_functions/code.py +143 -0
- amulet/game/translate/_functions/map_block_name.py +66 -0
- amulet/game/translate/_functions/map_nbt.py +111 -0
- amulet/game/translate/_functions/map_properties.py +93 -0
- amulet/game/translate/_functions/multiblock.py +112 -0
- amulet/game/translate/_functions/new_block.py +42 -0
- amulet/game/translate/_functions/new_entity.py +43 -0
- amulet/game/translate/_functions/new_nbt.py +206 -0
- amulet/game/translate/_functions/new_properties.py +64 -0
- amulet/game/translate/_functions/sequence.py +51 -0
- amulet/game/translate/_functions/walk_input_nbt.py +331 -0
- amulet/game/translate/_translator.py +433 -0
- amulet/item.py +75 -0
- amulet/level/__init__.pyi +27 -0
- amulet/level/_load.py +100 -0
- amulet/level/abc/__init__.py +12 -0
- amulet/level/abc/_chunk_handle.py +335 -0
- amulet/level/abc/_dimension.py +86 -0
- amulet/level/abc/_history/__init__.py +1 -0
- amulet/level/abc/_history/_cache.py +224 -0
- amulet/level/abc/_history/_history_manager.py +291 -0
- amulet/level/abc/_level/__init__.py +5 -0
- amulet/level/abc/_level/_compactable_level.py +10 -0
- amulet/level/abc/_level/_creatable_level.py +29 -0
- amulet/level/abc/_level/_disk_level.py +17 -0
- amulet/level/abc/_level/_level.py +453 -0
- amulet/level/abc/_level/_loadable_level.py +42 -0
- amulet/level/abc/_player_storage.py +7 -0
- amulet/level/abc/_raw_level.py +187 -0
- amulet/level/abc/_registry.py +40 -0
- amulet/level/bedrock/__init__.py +2 -0
- amulet/level/bedrock/_chunk_handle.py +19 -0
- amulet/level/bedrock/_dimension.py +22 -0
- amulet/level/bedrock/_level.py +187 -0
- amulet/level/bedrock/_raw/__init__.py +5 -0
- amulet/level/bedrock/_raw/_actor_counter.py +53 -0
- amulet/level/bedrock/_raw/_chunk.py +54 -0
- amulet/level/bedrock/_raw/_chunk_decode.py +668 -0
- amulet/level/bedrock/_raw/_chunk_encode.py +602 -0
- amulet/level/bedrock/_raw/_constant.py +9 -0
- amulet/level/bedrock/_raw/_dimension.py +343 -0
- amulet/level/bedrock/_raw/_level.py +463 -0
- amulet/level/bedrock/_raw/_level_dat.py +90 -0
- amulet/level/bedrock/_raw/_typing.py +6 -0
- amulet/level/bedrock/_raw/leveldb_chunk_versions.py +83 -0
- amulet/level/bedrock/chunk/__init__.py +1 -0
- amulet/level/bedrock/chunk/_chunk.py +126 -0
- amulet/level/bedrock/chunk/components/__init__.py +0 -0
- amulet/level/bedrock/chunk/components/chunk_version.py +12 -0
- amulet/level/bedrock/chunk/components/finalised_state.py +13 -0
- amulet/level/bedrock/chunk/components/raw_chunk.py +15 -0
- amulet/level/construction/__init__.py +0 -0
- amulet/level/java/__init__.pyi +21 -0
- amulet/level/java/_chunk_handle.py +17 -0
- amulet/level/java/_chunk_handle.pyi +15 -0
- amulet/level/java/_dimension.py +20 -0
- amulet/level/java/_dimension.pyi +13 -0
- amulet/level/java/_level.py +184 -0
- amulet/level/java/_level.pyi +120 -0
- amulet/level/java/_raw/__init__.pyi +19 -0
- amulet/level/java/_raw/_chunk.pyi +23 -0
- amulet/level/java/_raw/_chunk_decode.py +561 -0
- amulet/level/java/_raw/_chunk_encode.py +463 -0
- amulet/level/java/_raw/_constant.py +9 -0
- amulet/level/java/_raw/_constant.pyi +20 -0
- amulet/level/java/_raw/_data_pack/__init__.py +2 -0
- amulet/level/java/_raw/_data_pack/__init__.pyi +8 -0
- amulet/level/java/_raw/_data_pack/data_pack.py +241 -0
- amulet/level/java/_raw/_data_pack/data_pack.pyi +197 -0
- amulet/level/java/_raw/_data_pack/data_pack_manager.py +77 -0
- amulet/level/java/_raw/_data_pack/data_pack_manager.pyi +75 -0
- amulet/level/java/_raw/_dimension.py +86 -0
- amulet/level/java/_raw/_dimension.pyi +72 -0
- amulet/level/java/_raw/_level.py +507 -0
- amulet/level/java/_raw/_level.pyi +238 -0
- amulet/level/java/_raw/_typing.py +3 -0
- amulet/level/java/_raw/_typing.pyi +5 -0
- amulet/level/java/anvil/__init__.py +2 -0
- amulet/level/java/anvil/__init__.pyi +11 -0
- amulet/level/java/anvil/_dimension.py +170 -0
- amulet/level/java/anvil/_dimension.pyi +109 -0
- amulet/level/java/anvil/_region.py +421 -0
- amulet/level/java/anvil/_region.pyi +197 -0
- amulet/level/java/anvil/_sector_manager.py +223 -0
- amulet/level/java/anvil/_sector_manager.pyi +142 -0
- amulet/level/java/chunk.pyi +81 -0
- amulet/level/java/chunk_/_chunk.py +260 -0
- amulet/level/java/chunk_/components/inhabited_time.py +12 -0
- amulet/level/java/chunk_/components/last_update.py +12 -0
- amulet/level/java/chunk_/components/legacy_version.py +12 -0
- amulet/level/java/chunk_/components/light_populated.py +12 -0
- amulet/level/java/chunk_/components/named_height_2d.py +37 -0
- amulet/level/java/chunk_/components/status.py +11 -0
- amulet/level/java/chunk_/components/terrain_populated.py +12 -0
- amulet/level/java/chunk_components.pyi +22 -0
- amulet/level/java/long_array.pyi +38 -0
- amulet/level/java_forge/__init__.py +0 -0
- amulet/level/mcstructure/__init__.py +0 -0
- amulet/level/nbt/__init__.py +0 -0
- amulet/level/schematic/__init__.py +0 -0
- amulet/level/sponge_schematic/__init__.py +0 -0
- amulet/level/temporary_level/__init__.py +1 -0
- amulet/level/temporary_level/_level.py +16 -0
- amulet/palette/__init__.pyi +8 -0
- amulet/palette/biome_palette.pyi +45 -0
- amulet/palette/block_palette.pyi +45 -0
- amulet/player.py +64 -0
- amulet/py.typed +0 -0
- amulet/selection/__init__.py +2 -0
- amulet/selection/abstract_selection.py +342 -0
- amulet/selection/box.py +852 -0
- amulet/selection/group.py +481 -0
- amulet/utils/__init__.pyi +28 -0
- amulet/utils/call_spec/__init__.py +24 -0
- amulet/utils/call_spec/__init__.pyi +53 -0
- amulet/utils/call_spec/_call_spec.py +262 -0
- amulet/utils/call_spec/_call_spec.pyi +272 -0
- amulet/utils/format_utils.py +41 -0
- amulet/utils/generator.py +18 -0
- amulet/utils/matrix.py +243 -0
- amulet/utils/matrix.pyi +177 -0
- amulet/utils/numpy.pyi +11 -0
- amulet/utils/numpy_helpers.py +19 -0
- amulet/utils/shareable_lock.py +335 -0
- amulet/utils/shareable_lock.pyi +190 -0
- amulet/utils/signal/__init__.py +10 -0
- amulet/utils/signal/__init__.pyi +25 -0
- amulet/utils/signal/_signal.py +228 -0
- amulet/utils/signal/_signal.pyi +84 -0
- amulet/utils/task_manager.py +235 -0
- amulet/utils/task_manager.pyi +168 -0
- amulet/utils/typed_property.py +111 -0
- amulet/utils/typing.py +4 -0
- amulet/utils/typing.pyi +6 -0
- amulet/utils/weakref.py +70 -0
- amulet/utils/weakref.pyi +50 -0
- amulet/utils/world_utils.py +102 -0
- amulet/utils/world_utils.pyi +109 -0
- amulet/version.cpp +136 -0
- amulet/version.hpp +142 -0
- amulet/version.pyi +94 -0
- amulet_core-2.0a5.dist-info/METADATA +103 -0
- amulet_core-2.0a5.dist-info/RECORD +210 -0
- amulet_core-2.0a5.dist-info/WHEEL +5 -0
- amulet_core-2.0a5.dist-info/entry_points.txt +2 -0
- amulet_core-2.0a5.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,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"]
|