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,343 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Callable
|
|
4
|
+
import struct
|
|
5
|
+
from contextlib import suppress
|
|
6
|
+
import logging
|
|
7
|
+
from collections.abc import Iterator
|
|
8
|
+
|
|
9
|
+
from amulet_nbt import (
|
|
10
|
+
NamedTag,
|
|
11
|
+
LongTag,
|
|
12
|
+
StringTag,
|
|
13
|
+
CompoundTag,
|
|
14
|
+
NBTLoadError,
|
|
15
|
+
read_nbt,
|
|
16
|
+
utf8_escape_encoding,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from amulet.data_types import DimensionId, ChunkCoordinates
|
|
20
|
+
from amulet.block import Block, BlockStack
|
|
21
|
+
from amulet.biome import Biome
|
|
22
|
+
from amulet.selection import SelectionGroup
|
|
23
|
+
from amulet.errors import ChunkDoesNotExist
|
|
24
|
+
from amulet.version import VersionNumber
|
|
25
|
+
from amulet.level.abc import RawDimension, RawLevelFriend
|
|
26
|
+
from ._chunk import BedrockRawChunk
|
|
27
|
+
from ._chunk_decode import raw_to_native
|
|
28
|
+
from ._chunk_encode import native_to_raw
|
|
29
|
+
from ._constant import THE_NETHER, THE_END
|
|
30
|
+
from ._typing import InternalDimension
|
|
31
|
+
from ..chunk import BedrockChunk
|
|
32
|
+
|
|
33
|
+
if TYPE_CHECKING:
|
|
34
|
+
from ._level import BedrockRawLevel
|
|
35
|
+
|
|
36
|
+
log = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class BedrockRawDimension(
|
|
40
|
+
RawLevelFriend["BedrockRawLevel"], RawDimension[BedrockRawChunk, BedrockChunk]
|
|
41
|
+
):
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
raw_level_ref: Callable[[], BedrockRawLevel | None],
|
|
45
|
+
internal_dimension: InternalDimension,
|
|
46
|
+
alias: DimensionId,
|
|
47
|
+
bounds: SelectionGroup,
|
|
48
|
+
) -> None:
|
|
49
|
+
super().__init__(raw_level_ref)
|
|
50
|
+
self._internal_dimension = internal_dimension
|
|
51
|
+
self._alias = alias
|
|
52
|
+
self._bounds = bounds
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def dimension_id(self) -> DimensionId:
|
|
56
|
+
return self._alias
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def internal_dimension_id(self) -> InternalDimension:
|
|
60
|
+
return self._internal_dimension
|
|
61
|
+
|
|
62
|
+
def bounds(self) -> SelectionGroup:
|
|
63
|
+
"""The editable region of the dimension."""
|
|
64
|
+
return self._bounds
|
|
65
|
+
|
|
66
|
+
def default_block(self) -> BlockStack:
|
|
67
|
+
"""The default block for this dimension"""
|
|
68
|
+
return BlockStack(
|
|
69
|
+
Block("bedrock", VersionNumber(1, 20, 61), "minecraft", "air")
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def default_biome(self) -> Biome:
|
|
73
|
+
"""The default biome for this dimension"""
|
|
74
|
+
# todo: is this stored in the data somewhere?
|
|
75
|
+
if self.dimension_id == THE_NETHER:
|
|
76
|
+
return Biome("bedrock", VersionNumber(1, 20, 61), "minecraft", "hell")
|
|
77
|
+
elif self.dimension_id == THE_END:
|
|
78
|
+
return Biome("bedrock", VersionNumber(1, 20, 61), "minecraft", "the_end")
|
|
79
|
+
else:
|
|
80
|
+
return Biome("bedrock", VersionNumber(1, 20, 61), "minecraft", "plains")
|
|
81
|
+
|
|
82
|
+
def all_chunk_coords(self) -> Iterator[ChunkCoordinates]:
|
|
83
|
+
if self._internal_dimension is None:
|
|
84
|
+
mask = slice(8, 9)
|
|
85
|
+
key_len = 9
|
|
86
|
+
keys = (b",", b"v")
|
|
87
|
+
else:
|
|
88
|
+
mask = slice(8, 13)
|
|
89
|
+
key_len = 13
|
|
90
|
+
dim = struct.pack("<i", self._internal_dimension)
|
|
91
|
+
keys = (dim + b",", dim + b"v")
|
|
92
|
+
for key in self._r.level_db.keys():
|
|
93
|
+
if len(key) == key_len and key[mask] in keys:
|
|
94
|
+
yield struct.unpack("<ii", key[:8])
|
|
95
|
+
|
|
96
|
+
def _chunk_prefix(self, cx: int, cz: int) -> bytes:
|
|
97
|
+
if self._internal_dimension is None:
|
|
98
|
+
return struct.pack("<ii", cx, cz)
|
|
99
|
+
else:
|
|
100
|
+
return struct.pack("<iii", cx, cz, self._internal_dimension)
|
|
101
|
+
|
|
102
|
+
def has_chunk(self, cx: int, cz: int) -> bool:
|
|
103
|
+
key = self._chunk_prefix(cx, cz)
|
|
104
|
+
return any(key + tag in self._r.level_db for tag in (b",", b"v"))
|
|
105
|
+
|
|
106
|
+
def delete_chunk(self, cx: int, cz: int) -> None:
|
|
107
|
+
if not self.has_chunk(cx, cz):
|
|
108
|
+
return # chunk does not exists
|
|
109
|
+
|
|
110
|
+
db = self._r.level_db
|
|
111
|
+
prefix = self._chunk_prefix(cx, cz)
|
|
112
|
+
prefix_len = len(prefix)
|
|
113
|
+
iter_end = prefix + b"\xff\xff\xff\xff"
|
|
114
|
+
keys = []
|
|
115
|
+
for key, _ in db.iterate(prefix, iter_end):
|
|
116
|
+
if key[:prefix_len] == prefix and len(key) <= prefix_len + 2:
|
|
117
|
+
keys.append(key)
|
|
118
|
+
for key in keys:
|
|
119
|
+
db.delete(key)
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
digp = db.get(b"digp" + prefix)
|
|
123
|
+
except KeyError:
|
|
124
|
+
pass
|
|
125
|
+
else:
|
|
126
|
+
db.delete(b"digp" + prefix)
|
|
127
|
+
for i in range(0, len(digp) // 8 * 8, 8):
|
|
128
|
+
actor_key = b"actorprefix" + digp[i : i + 8]
|
|
129
|
+
db.delete(actor_key)
|
|
130
|
+
|
|
131
|
+
def get_raw_chunk(self, cx: int, cz: int) -> BedrockRawChunk:
|
|
132
|
+
"""Get the raw data for the chunk.
|
|
133
|
+
|
|
134
|
+
:param cx: The chunk x coordinate
|
|
135
|
+
:param cz: The chunk z coordinate
|
|
136
|
+
:return:
|
|
137
|
+
:raises:
|
|
138
|
+
ChunkDoesNotExist if the chunk does not exist
|
|
139
|
+
"""
|
|
140
|
+
if not self.has_chunk(cx, cz):
|
|
141
|
+
raise ChunkDoesNotExist
|
|
142
|
+
|
|
143
|
+
prefix = self._chunk_prefix(cx, cz)
|
|
144
|
+
prefix_len = len(prefix)
|
|
145
|
+
iter_end = prefix + b"\xff\xff\xff\xff"
|
|
146
|
+
|
|
147
|
+
chunk_data = BedrockRawChunk()
|
|
148
|
+
for key, val in self._r.level_db.iterate(prefix, iter_end):
|
|
149
|
+
if key[:prefix_len] == prefix and len(key) <= prefix_len + 2:
|
|
150
|
+
chunk_data.chunk_data[key[prefix_len:]] = val
|
|
151
|
+
|
|
152
|
+
with suppress(KeyError):
|
|
153
|
+
digp_key = b"digp" + prefix
|
|
154
|
+
digp = self._r.level_db.get(digp_key)
|
|
155
|
+
chunk_data.chunk_data[b"digp"] = (
|
|
156
|
+
b"" # The presence of this key signals to the put method that this should be created and written
|
|
157
|
+
)
|
|
158
|
+
for i in range(0, (len(digp) // 8) * 8, 8):
|
|
159
|
+
actor_key = b"actorprefix" + digp[i : i + 8]
|
|
160
|
+
try:
|
|
161
|
+
actor_bytes = self._r.level_db.get(actor_key)
|
|
162
|
+
actor = read_nbt(
|
|
163
|
+
actor_bytes,
|
|
164
|
+
little_endian=True,
|
|
165
|
+
string_encoding=utf8_escape_encoding,
|
|
166
|
+
)
|
|
167
|
+
actor_tag = actor.compound
|
|
168
|
+
except KeyError:
|
|
169
|
+
log.error(f"Could not find actor {actor_key!r}. Skipping.")
|
|
170
|
+
except NBTLoadError:
|
|
171
|
+
log.error(f"Failed to parse actor {actor_key!r}. Skipping.")
|
|
172
|
+
else:
|
|
173
|
+
actor_tag.pop("UniqueID", None)
|
|
174
|
+
internal_components = actor_tag.setdefault(
|
|
175
|
+
"internalComponents",
|
|
176
|
+
CompoundTag(
|
|
177
|
+
EntityStorageKeyComponent=CompoundTag(
|
|
178
|
+
StorageKey=StringTag()
|
|
179
|
+
)
|
|
180
|
+
),
|
|
181
|
+
) # 717
|
|
182
|
+
if (
|
|
183
|
+
isinstance(internal_components, CompoundTag)
|
|
184
|
+
and internal_components
|
|
185
|
+
):
|
|
186
|
+
if "EntityStorageKeyComponent" in internal_components:
|
|
187
|
+
# it is an entity
|
|
188
|
+
entity_component = internal_components[
|
|
189
|
+
"EntityStorageKeyComponent"
|
|
190
|
+
]
|
|
191
|
+
if isinstance(entity_component, CompoundTag):
|
|
192
|
+
# delete the storage key component
|
|
193
|
+
if isinstance(
|
|
194
|
+
entity_component.get("StorageKey"), StringTag
|
|
195
|
+
):
|
|
196
|
+
del entity_component["StorageKey"]
|
|
197
|
+
# if there is no other data then delete internalComponents
|
|
198
|
+
if (
|
|
199
|
+
len(entity_component) == 0
|
|
200
|
+
and len(internal_components) == 1
|
|
201
|
+
):
|
|
202
|
+
del actor_tag["internalComponents"]
|
|
203
|
+
else:
|
|
204
|
+
log.warning(
|
|
205
|
+
f"Extra components found {repr(entity_component)}"
|
|
206
|
+
)
|
|
207
|
+
else:
|
|
208
|
+
log.warning(
|
|
209
|
+
f"Unrecognised EntityStorageKeyComponent type {repr(entity_component)}"
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
chunk_data.entity_actor.append(actor)
|
|
213
|
+
else:
|
|
214
|
+
# it is an unknown actor
|
|
215
|
+
log.warning(
|
|
216
|
+
f"Actor {actor_key!r} has an unknown format. Please report this to a developer {repr(internal_components)}"
|
|
217
|
+
)
|
|
218
|
+
for k, v in internal_components.items():
|
|
219
|
+
if isinstance(v, CompoundTag) and isinstance(
|
|
220
|
+
v.get("StorageKey"), StringTag
|
|
221
|
+
):
|
|
222
|
+
v["StorageKey"] = StringTag()
|
|
223
|
+
chunk_data.unknown_actor.append(actor)
|
|
224
|
+
else:
|
|
225
|
+
log.error(
|
|
226
|
+
f"internalComponents was not valid for actor {actor_key!r}. Skipping."
|
|
227
|
+
)
|
|
228
|
+
continue
|
|
229
|
+
|
|
230
|
+
return chunk_data
|
|
231
|
+
|
|
232
|
+
def set_raw_chunk(self, cx: int, cz: int, chunk: BedrockRawChunk) -> None:
|
|
233
|
+
"""
|
|
234
|
+
Set the raw data for a chunk
|
|
235
|
+
:param cx: The chunk x coordinate
|
|
236
|
+
:param cz: The chunk z coordinate
|
|
237
|
+
:param chunk: The chunk data to set.
|
|
238
|
+
:return:
|
|
239
|
+
"""
|
|
240
|
+
key_prefix = self._chunk_prefix(cx, cz)
|
|
241
|
+
|
|
242
|
+
batch = {}
|
|
243
|
+
|
|
244
|
+
if b"digp" in chunk.chunk_data:
|
|
245
|
+
# if writing the digp key we need to delete all actors pointed to by the old digp key otherwise there will be memory leaks
|
|
246
|
+
digp_key = b"digp" + key_prefix
|
|
247
|
+
try:
|
|
248
|
+
old_digp = self._r.level_db.get(digp_key)
|
|
249
|
+
except KeyError:
|
|
250
|
+
pass
|
|
251
|
+
else:
|
|
252
|
+
for i in range(0, len(old_digp) // 8 * 8, 8):
|
|
253
|
+
actor_key = b"actorprefix" + old_digp[i : i + 8]
|
|
254
|
+
self._r.level_db.delete(actor_key)
|
|
255
|
+
|
|
256
|
+
digp = []
|
|
257
|
+
|
|
258
|
+
def add_actor(actor: NamedTag, is_entity: bool) -> None:
|
|
259
|
+
if not (
|
|
260
|
+
isinstance(actor, NamedTag) and isinstance(actor.tag, CompoundTag)
|
|
261
|
+
):
|
|
262
|
+
log.error(f"Actor must be a NamedTag[Compound]")
|
|
263
|
+
return
|
|
264
|
+
actor_tag = actor.compound
|
|
265
|
+
internal_components = actor_tag.setdefault(
|
|
266
|
+
"internalComponents", CompoundTag()
|
|
267
|
+
)
|
|
268
|
+
if not isinstance(internal_components, CompoundTag):
|
|
269
|
+
log.error(
|
|
270
|
+
f"Invalid internalComponents value. Must be Compound. Skipping. {repr(internal_components)}"
|
|
271
|
+
)
|
|
272
|
+
return
|
|
273
|
+
|
|
274
|
+
if is_entity:
|
|
275
|
+
entity_storage = internal_components.setdefault(
|
|
276
|
+
"EntityStorageKeyComponent", CompoundTag()
|
|
277
|
+
)
|
|
278
|
+
if not isinstance(entity_storage, CompoundTag):
|
|
279
|
+
log.error(
|
|
280
|
+
f"Invalid EntityStorageKeyComponent value. Must be Compound. Skipping. {repr(entity_storage)}"
|
|
281
|
+
)
|
|
282
|
+
return
|
|
283
|
+
storages = [entity_storage]
|
|
284
|
+
else:
|
|
285
|
+
storages = []
|
|
286
|
+
for storage in internal_components.values():
|
|
287
|
+
if (
|
|
288
|
+
isinstance(storage, CompoundTag)
|
|
289
|
+
and storage.get("StorageKey") == StringTag()
|
|
290
|
+
):
|
|
291
|
+
storages.append(storage)
|
|
292
|
+
if not storages:
|
|
293
|
+
log.error(
|
|
294
|
+
f"No valid StorageKeyComponent to write in for unknown actor {internal_components}"
|
|
295
|
+
)
|
|
296
|
+
return
|
|
297
|
+
|
|
298
|
+
session, uid = self._r._o.actor_counter.next()
|
|
299
|
+
# session is already negative
|
|
300
|
+
key = struct.pack(">ii", -session, uid)
|
|
301
|
+
# b'\x00\x00\x00\x01\x00\x00\x00\x0c' 1, 12
|
|
302
|
+
for storage in storages:
|
|
303
|
+
storage["StorageKey"] = StringTag(utf8_escape_encoding.decode(key))
|
|
304
|
+
# -4294967284 ">q" b'\xff\xff\xff\xff\x00\x00\x00\x0c' ">ii" -1, 12
|
|
305
|
+
actor_tag["UniqueID"] = LongTag(
|
|
306
|
+
struct.unpack(">q", struct.pack(">ii", session, uid))[0]
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
batch[b"actorprefix" + key] = actor.save_to(
|
|
310
|
+
little_endian=True,
|
|
311
|
+
compressed=False,
|
|
312
|
+
string_encoding=utf8_escape_encoding,
|
|
313
|
+
)
|
|
314
|
+
digp.append(key)
|
|
315
|
+
|
|
316
|
+
for actor_ in chunk.entity_actor:
|
|
317
|
+
add_actor(actor_, True)
|
|
318
|
+
|
|
319
|
+
for actor_ in chunk.unknown_actor:
|
|
320
|
+
add_actor(actor_, False)
|
|
321
|
+
|
|
322
|
+
del chunk.chunk_data[b"digp"]
|
|
323
|
+
batch[digp_key] = b"".join(digp)
|
|
324
|
+
|
|
325
|
+
# TODO: find all existing keys for this chunk in the database and delete them
|
|
326
|
+
for key, val in chunk.chunk_data.items():
|
|
327
|
+
key = key_prefix + key
|
|
328
|
+
if val is None:
|
|
329
|
+
self._r.level_db.delete(key)
|
|
330
|
+
else:
|
|
331
|
+
batch[key] = val
|
|
332
|
+
if batch:
|
|
333
|
+
self._r.level_db.putBatch(batch)
|
|
334
|
+
|
|
335
|
+
def raw_chunk_to_native_chunk(
|
|
336
|
+
self, raw_chunk: BedrockRawChunk, cx: int, cz: int
|
|
337
|
+
) -> BedrockChunk:
|
|
338
|
+
return raw_to_native(self._r, self, raw_chunk)
|
|
339
|
+
|
|
340
|
+
def native_chunk_to_raw_chunk(
|
|
341
|
+
self, chunk: BedrockChunk, cx: int, cz: int
|
|
342
|
+
) -> BedrockRawChunk:
|
|
343
|
+
return native_to_raw(self._r, self, chunk)
|