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