amulet-core 2.0a5__cp311-cp311-macosx_10_9_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-311-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,238 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import copy as copy
|
|
4
|
+
import glob as glob
|
|
5
|
+
import json as json
|
|
6
|
+
import logging as logging
|
|
7
|
+
import os as os
|
|
8
|
+
import shutil as shutil
|
|
9
|
+
import struct as struct
|
|
10
|
+
import time as time
|
|
11
|
+
import typing
|
|
12
|
+
from builtins import str as DimensionId
|
|
13
|
+
from builtins import str as InternalDimensionId
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from threading import RLock
|
|
16
|
+
from typing import BinaryIO
|
|
17
|
+
|
|
18
|
+
import amulet.level.abc._raw_level
|
|
19
|
+
import amulet.selection.group
|
|
20
|
+
import portalocker as portalocker
|
|
21
|
+
from amulet.biome import Biome
|
|
22
|
+
from amulet.block import Block, BlockStack
|
|
23
|
+
from amulet.errors import LevelWriteError
|
|
24
|
+
from amulet.game._game import get_game_version
|
|
25
|
+
from amulet.level.abc._raw_level import RawLevel
|
|
26
|
+
from amulet.level.abc._registry import IdRegistry
|
|
27
|
+
from amulet.level.java._raw._data_pack.data_pack import DataPack
|
|
28
|
+
from amulet.level.java._raw._data_pack.data_pack_manager import DataPackManager
|
|
29
|
+
from amulet.level.java._raw._dimension import JavaRawDimension
|
|
30
|
+
from amulet.level.java.anvil._dimension import AnvilDimension
|
|
31
|
+
from amulet.selection.box import SelectionBox
|
|
32
|
+
from amulet.selection.group import SelectionGroup
|
|
33
|
+
from amulet.utils.signal._signal import Signal
|
|
34
|
+
from amulet.utils.weakref import DetachableWeakRef
|
|
35
|
+
from amulet.version import VersionNumber
|
|
36
|
+
from amulet_nbt import (
|
|
37
|
+
CompoundTag,
|
|
38
|
+
IntTag,
|
|
39
|
+
ListTag,
|
|
40
|
+
LongTag,
|
|
41
|
+
NamedTag,
|
|
42
|
+
StringTag,
|
|
43
|
+
read_nbt,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
__all__ = [
|
|
47
|
+
"AnvilDimension",
|
|
48
|
+
"BinaryIO",
|
|
49
|
+
"Biome",
|
|
50
|
+
"Block",
|
|
51
|
+
"BlockStack",
|
|
52
|
+
"CompoundTag",
|
|
53
|
+
"DataPack",
|
|
54
|
+
"DataPackManager",
|
|
55
|
+
"DefaultSelection",
|
|
56
|
+
"DetachableWeakRef",
|
|
57
|
+
"DimensionId",
|
|
58
|
+
"IdRegistry",
|
|
59
|
+
"IntTag",
|
|
60
|
+
"InternalDimensionId",
|
|
61
|
+
"JavaCreateArgsV1",
|
|
62
|
+
"JavaRawDimension",
|
|
63
|
+
"JavaRawLevel",
|
|
64
|
+
"JavaRawLevelOpenData",
|
|
65
|
+
"LevelWriteError",
|
|
66
|
+
"ListTag",
|
|
67
|
+
"LongTag",
|
|
68
|
+
"NamedTag",
|
|
69
|
+
"OVERWORLD",
|
|
70
|
+
"RLock",
|
|
71
|
+
"RawLevel",
|
|
72
|
+
"SelectionBox",
|
|
73
|
+
"SelectionGroup",
|
|
74
|
+
"Signal",
|
|
75
|
+
"SignalInstanceCacheName",
|
|
76
|
+
"StringTag",
|
|
77
|
+
"THE_END",
|
|
78
|
+
"THE_NETHER",
|
|
79
|
+
"VersionNumber",
|
|
80
|
+
"copy",
|
|
81
|
+
"dataclass",
|
|
82
|
+
"get_game_version",
|
|
83
|
+
"glob",
|
|
84
|
+
"json",
|
|
85
|
+
"log",
|
|
86
|
+
"logging",
|
|
87
|
+
"os",
|
|
88
|
+
"portalocker",
|
|
89
|
+
"read_nbt",
|
|
90
|
+
"shutil",
|
|
91
|
+
"struct",
|
|
92
|
+
"time",
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
class JavaCreateArgsV1:
|
|
96
|
+
"""
|
|
97
|
+
A class to house call arguments to create.
|
|
98
|
+
|
|
99
|
+
If the call arguments to create need to be modified in the future a new arguments class can be created.
|
|
100
|
+
The create method can inspect which class it was given and access arguments accordingly.
|
|
101
|
+
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
__hash__: typing.ClassVar[None] = None
|
|
105
|
+
def __eq__(self, other): ...
|
|
106
|
+
def __init__(
|
|
107
|
+
self, overwrite: bool, path: str, version: VersionNumber, level_name: str
|
|
108
|
+
) -> None: ...
|
|
109
|
+
def __repr__(self): ...
|
|
110
|
+
|
|
111
|
+
class JavaRawLevel(amulet.level.abc._raw_level.RawLevel):
|
|
112
|
+
__slots__: typing.ClassVar[tuple] = (
|
|
113
|
+
"_path",
|
|
114
|
+
"_level_dat",
|
|
115
|
+
"_data_version",
|
|
116
|
+
"_raw_open_data",
|
|
117
|
+
"_SignalCache",
|
|
118
|
+
)
|
|
119
|
+
level_name: str
|
|
120
|
+
@staticmethod
|
|
121
|
+
def closed(*args, **kwargs): ...
|
|
122
|
+
@staticmethod
|
|
123
|
+
def opened(*args, **kwargs): ...
|
|
124
|
+
@classmethod
|
|
125
|
+
def create(cls, args: JavaCreateArgsV1) -> JavaRawLevel: ...
|
|
126
|
+
@classmethod
|
|
127
|
+
def load(cls, path: str) -> JavaRawLevel: ...
|
|
128
|
+
def __init__(self, _ikwiad: bool = False) -> None: ...
|
|
129
|
+
def _find_dimensions(self) -> None: ...
|
|
130
|
+
def _get_dimension_bounds(
|
|
131
|
+
self, dimension_type_str: DimensionId
|
|
132
|
+
) -> SelectionGroup: ...
|
|
133
|
+
def _register_dimension(
|
|
134
|
+
self, relative_dimension_path: InternalDimensionId, dimension_name: DimensionId
|
|
135
|
+
) -> None:
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
Register a new dimension.
|
|
139
|
+
|
|
140
|
+
:param relative_dimension_path: The relative path to the dimension directory from the world root.
|
|
141
|
+
"" for the world root.
|
|
142
|
+
:param dimension_name: The name of the dimension shown to the user
|
|
143
|
+
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
def _update_data_version(self) -> None:
|
|
147
|
+
"""
|
|
148
|
+
Pull the data version from the level.dat file
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
def close(self) -> None:
|
|
152
|
+
"""
|
|
153
|
+
Close the raw level.
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
def compact(self) -> None:
|
|
157
|
+
"""
|
|
158
|
+
Compact all region files
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
def dimension_ids(self) -> frozenset[DimensionId]: ...
|
|
162
|
+
def get_dimension(self, dimension_id: DimensionId) -> JavaRawDimension: ...
|
|
163
|
+
def is_open(self) -> bool: ...
|
|
164
|
+
def open(self) -> None:
|
|
165
|
+
"""
|
|
166
|
+
Open the raw level.
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
def reload(self) -> None:
|
|
170
|
+
"""
|
|
171
|
+
Reload the raw level.
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def _o(self) -> JavaRawLevelOpenData: ...
|
|
176
|
+
@property
|
|
177
|
+
def biome_id_override(self) -> IdRegistry:
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
A two-way map from hard coded numerical biome id <-> biome string.
|
|
181
|
+
This only stores overridden values. If the value is not present here you should check the translator.
|
|
182
|
+
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def block_id_override(self) -> IdRegistry:
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
A two-way map from hard coded numerical block id <-> block string.
|
|
190
|
+
This only stores overridden values. If the value is not present here you should check the translator.
|
|
191
|
+
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def data_version(self) -> VersionNumber:
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
The game data version that the level was last opened in.
|
|
199
|
+
This is used to determine the data format to save in.
|
|
200
|
+
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
@property
|
|
204
|
+
def level_dat(self) -> NamedTag:
|
|
205
|
+
"""
|
|
206
|
+
Get the level.dat file for the world
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
@level_dat.setter
|
|
210
|
+
def level_dat(self, level_dat: NamedTag) -> None: ...
|
|
211
|
+
@property
|
|
212
|
+
def modified_time(self) -> float:
|
|
213
|
+
"""
|
|
214
|
+
Unix timestamp of when the level was last modified.
|
|
215
|
+
"""
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def path(self) -> str: ...
|
|
219
|
+
@property
|
|
220
|
+
def platform(self) -> str: ...
|
|
221
|
+
|
|
222
|
+
class JavaRawLevelOpenData:
|
|
223
|
+
def __init__(
|
|
224
|
+
self,
|
|
225
|
+
raw_level: JavaRawLevel,
|
|
226
|
+
lock_file: BinaryIO,
|
|
227
|
+
lock_time: float,
|
|
228
|
+
data_pack: DataPackManager,
|
|
229
|
+
) -> None: ...
|
|
230
|
+
|
|
231
|
+
DefaultSelection: (
|
|
232
|
+
amulet.selection.group.SelectionGroup
|
|
233
|
+
) # value = SelectionGroup([SelectionBox((-30000000, 0, -30000000), (30000000, 256, 30000000))])
|
|
234
|
+
OVERWORLD: str
|
|
235
|
+
SignalInstanceCacheName: str
|
|
236
|
+
THE_END: str
|
|
237
|
+
THE_NETHER: str
|
|
238
|
+
log: logging.Logger # value = <Logger amulet.level.java._raw._level (INFO)>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import types
|
|
4
|
+
|
|
5
|
+
from amulet.level.java.anvil._dimension import AnvilDimension, AnvilDimensionLayer
|
|
6
|
+
from amulet.level.java.anvil._region import AnvilRegion
|
|
7
|
+
|
|
8
|
+
from . import _dimension, _region, _sector_manager
|
|
9
|
+
|
|
10
|
+
__all__ = ["AnvilDimension", "AnvilDimensionLayer", "AnvilRegion", "RawChunkType"]
|
|
11
|
+
RawChunkType: types.GenericAlias # value = dict[str, amulet_nbt.NamedTag]
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TypeAlias
|
|
4
|
+
import os
|
|
5
|
+
from collections.abc import Iterator, Sequence
|
|
6
|
+
import re
|
|
7
|
+
import threading
|
|
8
|
+
|
|
9
|
+
from amulet_nbt import NamedTag
|
|
10
|
+
|
|
11
|
+
from amulet.utils import world_utils
|
|
12
|
+
from amulet.errors import ChunkDoesNotExist
|
|
13
|
+
from amulet.data_types import (
|
|
14
|
+
ChunkCoordinates,
|
|
15
|
+
RegionCoordinates,
|
|
16
|
+
)
|
|
17
|
+
from ._region import AnvilRegion
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
RawChunkType: TypeAlias = dict[str, NamedTag]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AnvilDimensionLayer:
|
|
24
|
+
"""A class to manage a directory of region files."""
|
|
25
|
+
|
|
26
|
+
def __init__(self, directory: str, *, mcc: bool = False):
|
|
27
|
+
self._directory = directory
|
|
28
|
+
self._regions: dict[RegionCoordinates, AnvilRegion] = {}
|
|
29
|
+
self._mcc = mcc
|
|
30
|
+
self._lock = threading.RLock()
|
|
31
|
+
|
|
32
|
+
def _region_path(self, rx: int, rz: int) -> str:
|
|
33
|
+
"""Get the file path for a region file."""
|
|
34
|
+
return os.path.join(self._directory, f"r.{rx}.{rz}.mca")
|
|
35
|
+
|
|
36
|
+
def _has_region(self, rx: int, rz: int) -> bool:
|
|
37
|
+
"""Does a region file exist."""
|
|
38
|
+
return os.path.isfile(self._region_path(rx, rz))
|
|
39
|
+
|
|
40
|
+
def _get_region(self, rx: int, rz: int, create: bool = False) -> AnvilRegion:
|
|
41
|
+
with self._lock:
|
|
42
|
+
if (rx, rz) in self._regions:
|
|
43
|
+
return self._regions[(rx, rz)]
|
|
44
|
+
elif create or self._has_region(rx, rz):
|
|
45
|
+
region = self._regions[(rx, rz)] = AnvilRegion(
|
|
46
|
+
self._region_path(rx, rz), mcc=self._mcc
|
|
47
|
+
)
|
|
48
|
+
return region
|
|
49
|
+
else:
|
|
50
|
+
raise ChunkDoesNotExist
|
|
51
|
+
|
|
52
|
+
def _iter_regions(self) -> Iterator[AnvilRegion]:
|
|
53
|
+
if os.path.isdir(self._directory):
|
|
54
|
+
for region_file_name in os.listdir(self._directory):
|
|
55
|
+
try:
|
|
56
|
+
rx, rz = AnvilRegion.get_coords(region_file_name)
|
|
57
|
+
except ValueError:
|
|
58
|
+
continue
|
|
59
|
+
else:
|
|
60
|
+
yield self._get_region(rx, rz)
|
|
61
|
+
|
|
62
|
+
def all_chunk_coords(self) -> Iterator[ChunkCoordinates]:
|
|
63
|
+
for region in self._iter_regions():
|
|
64
|
+
yield from region.all_coords()
|
|
65
|
+
|
|
66
|
+
def has_chunk(self, cx: int, cz: int) -> bool:
|
|
67
|
+
try:
|
|
68
|
+
region = self._get_region(
|
|
69
|
+
*world_utils.chunk_coords_to_region_coords(cx, cz)
|
|
70
|
+
)
|
|
71
|
+
except ChunkDoesNotExist:
|
|
72
|
+
return False
|
|
73
|
+
else:
|
|
74
|
+
return region.has_data(cx, cz)
|
|
75
|
+
|
|
76
|
+
def get_chunk_data(self, cx: int, cz: int) -> NamedTag:
|
|
77
|
+
"""
|
|
78
|
+
Get a NamedTag of a chunk from the database.
|
|
79
|
+
Will raise ChunkDoesNotExist if the region or chunk does not exist
|
|
80
|
+
"""
|
|
81
|
+
# get the region key
|
|
82
|
+
return self._get_region(
|
|
83
|
+
*world_utils.chunk_coords_to_region_coords(cx, cz)
|
|
84
|
+
).get_data(cx, cz)
|
|
85
|
+
|
|
86
|
+
def put_chunk_data(self, cx: int, cz: int, data: NamedTag) -> None:
|
|
87
|
+
"""pass data to the region file class"""
|
|
88
|
+
self._get_region(
|
|
89
|
+
*world_utils.chunk_coords_to_region_coords(cx, cz), create=True
|
|
90
|
+
).set_data(cx, cz, data)
|
|
91
|
+
|
|
92
|
+
def delete_chunk(self, cx: int, cz: int) -> None:
|
|
93
|
+
try:
|
|
94
|
+
region = self._get_region(
|
|
95
|
+
*world_utils.chunk_coords_to_region_coords(cx, cz)
|
|
96
|
+
)
|
|
97
|
+
except ChunkDoesNotExist:
|
|
98
|
+
pass
|
|
99
|
+
else:
|
|
100
|
+
region.delete_data(cx, cz)
|
|
101
|
+
|
|
102
|
+
def compact(self) -> None:
|
|
103
|
+
"""Compact all region files in this layer"""
|
|
104
|
+
for region in self._iter_regions():
|
|
105
|
+
region.compact()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class AnvilDimension:
|
|
109
|
+
"""
|
|
110
|
+
A class to manage the data for a dimension.
|
|
111
|
+
This can consist of multiple layers. Eg the region layer which contains chunk data and the entities layer which contains entities.
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
level_regex = re.compile(r"DIM(?P<level>-?\d+)")
|
|
115
|
+
|
|
116
|
+
def __init__(
|
|
117
|
+
self, directory: str, *, mcc: bool = False, layers: Sequence[str] = ("region",)
|
|
118
|
+
) -> None:
|
|
119
|
+
self._directory = directory
|
|
120
|
+
self._mcc = mcc
|
|
121
|
+
self.__layers: dict[str, AnvilDimensionLayer] = {
|
|
122
|
+
layer: AnvilDimensionLayer(
|
|
123
|
+
os.path.join(self._directory, layer), mcc=self._mcc
|
|
124
|
+
)
|
|
125
|
+
for layer in layers
|
|
126
|
+
}
|
|
127
|
+
self.__default_layer = self.__layers[layers[0]]
|
|
128
|
+
|
|
129
|
+
def all_chunk_coords(self) -> Iterator[ChunkCoordinates]:
|
|
130
|
+
yield from self.__default_layer.all_chunk_coords()
|
|
131
|
+
|
|
132
|
+
def has_chunk(self, cx: int, cz: int) -> bool:
|
|
133
|
+
return self.__default_layer.has_chunk(cx, cz)
|
|
134
|
+
|
|
135
|
+
def get_chunk_data(self, cx: int, cz: int) -> RawChunkType:
|
|
136
|
+
"""Get the chunk data for each layer"""
|
|
137
|
+
chunk_data = {}
|
|
138
|
+
for layer_name, layer in self.__layers.items():
|
|
139
|
+
try:
|
|
140
|
+
chunk_data[layer_name] = layer.get_chunk_data(cx, cz)
|
|
141
|
+
except ChunkDoesNotExist:
|
|
142
|
+
pass
|
|
143
|
+
|
|
144
|
+
if chunk_data:
|
|
145
|
+
return chunk_data
|
|
146
|
+
else:
|
|
147
|
+
raise ChunkDoesNotExist
|
|
148
|
+
|
|
149
|
+
def put_chunk_data(self, cx: int, cz: int, data_layers: RawChunkType) -> None:
|
|
150
|
+
"""Put one or more layers of data"""
|
|
151
|
+
for layer_name, data in data_layers.items():
|
|
152
|
+
if (
|
|
153
|
+
layer_name not in self.__layers
|
|
154
|
+
and layer_name.isalpha()
|
|
155
|
+
and layer_name.islower()
|
|
156
|
+
):
|
|
157
|
+
self.__layers[layer_name] = AnvilDimensionLayer(
|
|
158
|
+
os.path.join(self._directory, layer_name), mcc=self._mcc
|
|
159
|
+
)
|
|
160
|
+
if layer_name in self.__layers:
|
|
161
|
+
self.__layers[layer_name].put_chunk_data(cx, cz, data)
|
|
162
|
+
|
|
163
|
+
def delete_chunk(self, cx: int, cz: int) -> None:
|
|
164
|
+
for layer in self.__layers.values():
|
|
165
|
+
layer.delete_chunk(cx, cz)
|
|
166
|
+
|
|
167
|
+
def compact(self) -> None:
|
|
168
|
+
"""Compact all region files in this dimension"""
|
|
169
|
+
for layer in self.__layers.values():
|
|
170
|
+
layer.compact()
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os as os
|
|
4
|
+
import re as re
|
|
5
|
+
import threading as threading
|
|
6
|
+
import types
|
|
7
|
+
import typing
|
|
8
|
+
from collections.abc import Iterator, Sequence
|
|
9
|
+
|
|
10
|
+
from amulet.errors import ChunkDoesNotExist
|
|
11
|
+
from amulet.level.java.anvil._region import AnvilRegion
|
|
12
|
+
from amulet.utils import world_utils
|
|
13
|
+
from amulet_nbt import NamedTag
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"AnvilDimension",
|
|
17
|
+
"AnvilDimensionLayer",
|
|
18
|
+
"AnvilRegion",
|
|
19
|
+
"ChunkCoordinates",
|
|
20
|
+
"ChunkDoesNotExist",
|
|
21
|
+
"Iterator",
|
|
22
|
+
"NamedTag",
|
|
23
|
+
"RawChunkType",
|
|
24
|
+
"RegionCoordinates",
|
|
25
|
+
"Sequence",
|
|
26
|
+
"os",
|
|
27
|
+
"re",
|
|
28
|
+
"threading",
|
|
29
|
+
"world_utils",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
class AnvilDimension:
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
A class to manage the data for a dimension.
|
|
36
|
+
This can consist of multiple layers. Eg the region layer which contains chunk data and the entities layer which contains entities.
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
level_regex: typing.ClassVar[
|
|
41
|
+
re.Pattern
|
|
42
|
+
] # value = re.compile('DIM(?P<level>-?\\d+)')
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
directory: str,
|
|
46
|
+
*,
|
|
47
|
+
mcc: bool = False,
|
|
48
|
+
layers: typing.Sequence[str] = ("region"),
|
|
49
|
+
) -> None: ...
|
|
50
|
+
def all_chunk_coords(self) -> typing.Iterator[ChunkCoordinates]: ...
|
|
51
|
+
def compact(self) -> None:
|
|
52
|
+
"""
|
|
53
|
+
Compact all region files in this dimension
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
def delete_chunk(self, cx: int, cz: int) -> None: ...
|
|
57
|
+
def get_chunk_data(self, cx: int, cz: int) -> RawChunkType:
|
|
58
|
+
"""
|
|
59
|
+
Get the chunk data for each layer
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def has_chunk(self, cx: int, cz: int) -> bool: ...
|
|
63
|
+
def put_chunk_data(self, cx: int, cz: int, data_layers: RawChunkType) -> None:
|
|
64
|
+
"""
|
|
65
|
+
Put one or more layers of data
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
class AnvilDimensionLayer:
|
|
69
|
+
"""
|
|
70
|
+
A class to manage a directory of region files.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
def __init__(self, directory: str, *, mcc: bool = False): ...
|
|
74
|
+
def _get_region(self, rx: int, rz: int, create: bool = False) -> AnvilRegion: ...
|
|
75
|
+
def _has_region(self, rx: int, rz: int) -> bool:
|
|
76
|
+
"""
|
|
77
|
+
Does a region file exist.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
def _iter_regions(self) -> typing.Iterator[AnvilRegion]: ...
|
|
81
|
+
def _region_path(self, rx: int, rz: int) -> str:
|
|
82
|
+
"""
|
|
83
|
+
Get the file path for a region file.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def all_chunk_coords(self) -> typing.Iterator[ChunkCoordinates]: ...
|
|
87
|
+
def compact(self) -> None:
|
|
88
|
+
"""
|
|
89
|
+
Compact all region files in this layer
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
def delete_chunk(self, cx: int, cz: int) -> None: ...
|
|
93
|
+
def get_chunk_data(self, cx: int, cz: int) -> NamedTag:
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
Get a NamedTag of a chunk from the database.
|
|
97
|
+
Will raise ChunkDoesNotExist if the region or chunk does not exist
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
def has_chunk(self, cx: int, cz: int) -> bool: ...
|
|
102
|
+
def put_chunk_data(self, cx: int, cz: int, data: NamedTag) -> None:
|
|
103
|
+
"""
|
|
104
|
+
pass data to the region file class
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
ChunkCoordinates: types.GenericAlias # value = tuple[int, int]
|
|
108
|
+
RawChunkType: types.GenericAlias # value = dict[str, amulet_nbt.NamedTag]
|
|
109
|
+
RegionCoordinates: types.GenericAlias # value = tuple[int, int]
|