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,116 +1,116 @@
|
|
|
1
|
-
from abc import abstractmethod
|
|
2
|
-
from typing import BinaryIO, List, Any, Tuple, Iterable, Union, Optional, Dict
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
from .format_wrapper import FormatWrapper, VersionNumberT
|
|
6
|
-
from amulet.api.data_types import Dimension
|
|
7
|
-
from amulet.api.errors import ObjectReadError, ObjectReadWriteError, PlayerDoesNotExist
|
|
8
|
-
from amulet.api.player import Player
|
|
9
|
-
from amulet.api.selection import SelectionGroup
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class StructureFormatWrapper(FormatWrapper[VersionNumberT]):
|
|
13
|
-
"""A base FormatWrapper for all structures that only have one dimension."""
|
|
14
|
-
|
|
15
|
-
def __init__(self, path: str):
|
|
16
|
-
"""
|
|
17
|
-
Construct a new instance of :class:`StructureFormatWrapper`.
|
|
18
|
-
|
|
19
|
-
This should not be used directly. You should instead use :func:`amulet.load_format`.
|
|
20
|
-
|
|
21
|
-
:param path: The file path to the serialised data.
|
|
22
|
-
"""
|
|
23
|
-
super().__init__(path)
|
|
24
|
-
if self.extensions:
|
|
25
|
-
ext = os.path.splitext(self._path)[1]
|
|
26
|
-
if ext not in self.extensions:
|
|
27
|
-
raise ObjectReadWriteError(
|
|
28
|
-
f"The given file does not have a valid file extension. Must be one of {self.extensions}"
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
@property
|
|
32
|
-
def level_name(self) -> str:
|
|
33
|
-
return os.path.basename(self.path)
|
|
34
|
-
|
|
35
|
-
@property
|
|
36
|
-
def dimensions(self) -> List[Dimension]:
|
|
37
|
-
return ["main"]
|
|
38
|
-
|
|
39
|
-
@property
|
|
40
|
-
def can_add_dimension(self) -> bool:
|
|
41
|
-
return False
|
|
42
|
-
|
|
43
|
-
def register_dimension(self, dimension_identifier: Any):
|
|
44
|
-
pass
|
|
45
|
-
|
|
46
|
-
@property
|
|
47
|
-
def requires_selection(self) -> bool:
|
|
48
|
-
return True
|
|
49
|
-
|
|
50
|
-
@property
|
|
51
|
-
@abstractmethod
|
|
52
|
-
def extensions(self) -> Tuple[str, ...]:
|
|
53
|
-
"""
|
|
54
|
-
The extension the file can have to be valid.
|
|
55
|
-
|
|
56
|
-
eg (".schematic",)
|
|
57
|
-
"""
|
|
58
|
-
raise NotImplementedError
|
|
59
|
-
|
|
60
|
-
def _set_selection(
|
|
61
|
-
self,
|
|
62
|
-
bounds: Union[SelectionGroup, Dict[Dimension, Optional[SelectionGroup]], None],
|
|
63
|
-
):
|
|
64
|
-
if isinstance(bounds, SelectionGroup):
|
|
65
|
-
bounds = self._clean_selection(bounds)
|
|
66
|
-
self._bounds = {dim: bounds for dim in self.dimensions}
|
|
67
|
-
elif isinstance(bounds, dict):
|
|
68
|
-
for dim in self.dimensions:
|
|
69
|
-
group = bounds.get(dim, None)
|
|
70
|
-
if isinstance(group, SelectionGroup):
|
|
71
|
-
self._bounds[dim] = self._clean_selection(group)
|
|
72
|
-
else:
|
|
73
|
-
raise ObjectReadError("A selection was required but none were given.")
|
|
74
|
-
|
|
75
|
-
@abstractmethod
|
|
76
|
-
def open_from(self, f: BinaryIO):
|
|
77
|
-
"""
|
|
78
|
-
Load from a file like object. Useful to load from RAM rather than disk.
|
|
79
|
-
|
|
80
|
-
:param f: The file like object to read data from.
|
|
81
|
-
"""
|
|
82
|
-
raise NotImplementedError
|
|
83
|
-
|
|
84
|
-
def _open(self):
|
|
85
|
-
if not os.path.isfile(self._path):
|
|
86
|
-
raise ObjectReadError(f"There is no file to read at {self._path}")
|
|
87
|
-
with open(self._path, "rb") as f:
|
|
88
|
-
self.open_from(f)
|
|
89
|
-
self._is_open = True
|
|
90
|
-
self._has_lock = True
|
|
91
|
-
|
|
92
|
-
@abstractmethod
|
|
93
|
-
def save_to(self, f: BinaryIO):
|
|
94
|
-
"""
|
|
95
|
-
Write to a file like object. Useful to write to RAM rather than disk.
|
|
96
|
-
|
|
97
|
-
:param f: The file like object to write data to.
|
|
98
|
-
"""
|
|
99
|
-
raise NotImplementedError
|
|
100
|
-
|
|
101
|
-
def _save(self):
|
|
102
|
-
os.makedirs(os.path.dirname(self._path), exist_ok=True)
|
|
103
|
-
with open(self._path, "wb") as f:
|
|
104
|
-
self.save_to(f)
|
|
105
|
-
|
|
106
|
-
def all_player_ids(self) -> Iterable[str]:
|
|
107
|
-
yield from ()
|
|
108
|
-
|
|
109
|
-
def has_player(self, player_id: str) -> bool:
|
|
110
|
-
return False
|
|
111
|
-
|
|
112
|
-
def _load_player(self, player_id: str) -> Player:
|
|
113
|
-
raise PlayerDoesNotExist
|
|
114
|
-
|
|
115
|
-
def _get_raw_player_data(self, player_id: str) -> Any:
|
|
116
|
-
raise PlayerDoesNotExist
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
from typing import BinaryIO, List, Any, Tuple, Iterable, Union, Optional, Dict
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
from .format_wrapper import FormatWrapper, VersionNumberT
|
|
6
|
+
from amulet.api.data_types import Dimension
|
|
7
|
+
from amulet.api.errors import ObjectReadError, ObjectReadWriteError, PlayerDoesNotExist
|
|
8
|
+
from amulet.api.player import Player
|
|
9
|
+
from amulet.api.selection import SelectionGroup
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class StructureFormatWrapper(FormatWrapper[VersionNumberT]):
|
|
13
|
+
"""A base FormatWrapper for all structures that only have one dimension."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, path: str):
|
|
16
|
+
"""
|
|
17
|
+
Construct a new instance of :class:`StructureFormatWrapper`.
|
|
18
|
+
|
|
19
|
+
This should not be used directly. You should instead use :func:`amulet.load_format`.
|
|
20
|
+
|
|
21
|
+
:param path: The file path to the serialised data.
|
|
22
|
+
"""
|
|
23
|
+
super().__init__(path)
|
|
24
|
+
if self.extensions:
|
|
25
|
+
ext = os.path.splitext(self._path)[1]
|
|
26
|
+
if ext not in self.extensions:
|
|
27
|
+
raise ObjectReadWriteError(
|
|
28
|
+
f"The given file does not have a valid file extension. Must be one of {self.extensions}"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def level_name(self) -> str:
|
|
33
|
+
return os.path.basename(self.path)
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def dimensions(self) -> List[Dimension]:
|
|
37
|
+
return ["main"]
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def can_add_dimension(self) -> bool:
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
def register_dimension(self, dimension_identifier: Any):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def requires_selection(self) -> bool:
|
|
48
|
+
return True
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
@abstractmethod
|
|
52
|
+
def extensions(self) -> Tuple[str, ...]:
|
|
53
|
+
"""
|
|
54
|
+
The extension the file can have to be valid.
|
|
55
|
+
|
|
56
|
+
eg (".schematic",)
|
|
57
|
+
"""
|
|
58
|
+
raise NotImplementedError
|
|
59
|
+
|
|
60
|
+
def _set_selection(
|
|
61
|
+
self,
|
|
62
|
+
bounds: Union[SelectionGroup, Dict[Dimension, Optional[SelectionGroup]], None],
|
|
63
|
+
):
|
|
64
|
+
if isinstance(bounds, SelectionGroup):
|
|
65
|
+
bounds = self._clean_selection(bounds)
|
|
66
|
+
self._bounds = {dim: bounds for dim in self.dimensions}
|
|
67
|
+
elif isinstance(bounds, dict):
|
|
68
|
+
for dim in self.dimensions:
|
|
69
|
+
group = bounds.get(dim, None)
|
|
70
|
+
if isinstance(group, SelectionGroup):
|
|
71
|
+
self._bounds[dim] = self._clean_selection(group)
|
|
72
|
+
else:
|
|
73
|
+
raise ObjectReadError("A selection was required but none were given.")
|
|
74
|
+
|
|
75
|
+
@abstractmethod
|
|
76
|
+
def open_from(self, f: BinaryIO):
|
|
77
|
+
"""
|
|
78
|
+
Load from a file like object. Useful to load from RAM rather than disk.
|
|
79
|
+
|
|
80
|
+
:param f: The file like object to read data from.
|
|
81
|
+
"""
|
|
82
|
+
raise NotImplementedError
|
|
83
|
+
|
|
84
|
+
def _open(self):
|
|
85
|
+
if not os.path.isfile(self._path):
|
|
86
|
+
raise ObjectReadError(f"There is no file to read at {self._path}")
|
|
87
|
+
with open(self._path, "rb") as f:
|
|
88
|
+
self.open_from(f)
|
|
89
|
+
self._is_open = True
|
|
90
|
+
self._has_lock = True
|
|
91
|
+
|
|
92
|
+
@abstractmethod
|
|
93
|
+
def save_to(self, f: BinaryIO):
|
|
94
|
+
"""
|
|
95
|
+
Write to a file like object. Useful to write to RAM rather than disk.
|
|
96
|
+
|
|
97
|
+
:param f: The file like object to write data to.
|
|
98
|
+
"""
|
|
99
|
+
raise NotImplementedError
|
|
100
|
+
|
|
101
|
+
def _save(self):
|
|
102
|
+
os.makedirs(os.path.dirname(self._path), exist_ok=True)
|
|
103
|
+
with open(self._path, "wb") as f:
|
|
104
|
+
self.save_to(f)
|
|
105
|
+
|
|
106
|
+
def all_player_ids(self) -> Iterable[str]:
|
|
107
|
+
yield from ()
|
|
108
|
+
|
|
109
|
+
def has_player(self, player_id: str) -> bool:
|
|
110
|
+
return False
|
|
111
|
+
|
|
112
|
+
def _load_player(self, player_id: str) -> Player:
|
|
113
|
+
raise PlayerDoesNotExist
|
|
114
|
+
|
|
115
|
+
def _get_raw_player_data(self, player_id: str) -> Any:
|
|
116
|
+
raise PlayerDoesNotExist
|
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
from abc import abstractmethod
|
|
2
|
-
import os
|
|
3
|
-
from typing import Any, Optional, TYPE_CHECKING
|
|
4
|
-
|
|
5
|
-
from amulet import IMG_DIRECTORY
|
|
6
|
-
from .format_wrapper import FormatWrapper, VersionNumberT
|
|
7
|
-
|
|
8
|
-
if TYPE_CHECKING:
|
|
9
|
-
from amulet.api.wrapper import Interface
|
|
10
|
-
|
|
11
|
-
missing_world_icon = os.path.abspath(
|
|
12
|
-
os.path.join(IMG_DIRECTORY, "missing_world_icon.png")
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class WorldFormatWrapper(FormatWrapper[VersionNumberT]):
|
|
17
|
-
_missing_world_icon = missing_world_icon
|
|
18
|
-
|
|
19
|
-
def __init__(self, path: str):
|
|
20
|
-
"""
|
|
21
|
-
Construct a new instance of :class:`WorldFormatWrapper`.
|
|
22
|
-
|
|
23
|
-
This should not be used directly. You should instead use :func:`amulet.load_format`.
|
|
24
|
-
|
|
25
|
-
:param path: The file path to the serialised data.
|
|
26
|
-
"""
|
|
27
|
-
super().__init__(path)
|
|
28
|
-
self._world_image_path = missing_world_icon
|
|
29
|
-
|
|
30
|
-
@property
|
|
31
|
-
@abstractmethod
|
|
32
|
-
def level_name(self) -> str:
|
|
33
|
-
raise NotImplementedError
|
|
34
|
-
|
|
35
|
-
@level_name.setter
|
|
36
|
-
@abstractmethod
|
|
37
|
-
def level_name(self, value: str):
|
|
38
|
-
raise NotImplementedError
|
|
39
|
-
|
|
40
|
-
@property
|
|
41
|
-
@abstractmethod
|
|
42
|
-
def last_played(self) -> int:
|
|
43
|
-
raise NotImplementedError
|
|
44
|
-
|
|
45
|
-
@property
|
|
46
|
-
@abstractmethod
|
|
47
|
-
def game_version_string(self) -> str:
|
|
48
|
-
raise NotImplementedError
|
|
49
|
-
|
|
50
|
-
@property
|
|
51
|
-
def world_image_path(self) -> str:
|
|
52
|
-
"""The path to the world icon."""
|
|
53
|
-
return self._world_image_path
|
|
54
|
-
|
|
55
|
-
@property
|
|
56
|
-
def can_add_dimension(self) -> bool:
|
|
57
|
-
return False
|
|
58
|
-
|
|
59
|
-
def register_dimension(self, dimension_identifier: Any):
|
|
60
|
-
pass
|
|
61
|
-
|
|
62
|
-
def _get_interface(self, raw_chunk_data: Optional[Any] = None) -> "Interface":
|
|
63
|
-
raise NotImplementedError
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
import os
|
|
3
|
+
from typing import Any, Optional, TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from amulet import IMG_DIRECTORY
|
|
6
|
+
from .format_wrapper import FormatWrapper, VersionNumberT
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from amulet.api.wrapper import Interface
|
|
10
|
+
|
|
11
|
+
missing_world_icon = os.path.abspath(
|
|
12
|
+
os.path.join(IMG_DIRECTORY, "missing_world_icon.png")
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class WorldFormatWrapper(FormatWrapper[VersionNumberT]):
|
|
17
|
+
_missing_world_icon = missing_world_icon
|
|
18
|
+
|
|
19
|
+
def __init__(self, path: str):
|
|
20
|
+
"""
|
|
21
|
+
Construct a new instance of :class:`WorldFormatWrapper`.
|
|
22
|
+
|
|
23
|
+
This should not be used directly. You should instead use :func:`amulet.load_format`.
|
|
24
|
+
|
|
25
|
+
:param path: The file path to the serialised data.
|
|
26
|
+
"""
|
|
27
|
+
super().__init__(path)
|
|
28
|
+
self._world_image_path = missing_world_icon
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def level_name(self) -> str:
|
|
33
|
+
raise NotImplementedError
|
|
34
|
+
|
|
35
|
+
@level_name.setter
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def level_name(self, value: str):
|
|
38
|
+
raise NotImplementedError
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def last_played(self) -> int:
|
|
43
|
+
raise NotImplementedError
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def game_version_string(self) -> str:
|
|
48
|
+
raise NotImplementedError
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def world_image_path(self) -> str:
|
|
52
|
+
"""The path to the world icon."""
|
|
53
|
+
return self._world_image_path
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def can_add_dimension(self) -> bool:
|
|
57
|
+
return False
|
|
58
|
+
|
|
59
|
+
def register_dimension(self, dimension_identifier: Any):
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
def _get_interface(self, raw_chunk_data: Optional[Any] = None) -> "Interface":
|
|
63
|
+
raise NotImplementedError
|
amulet/level/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
from .load import load_format, load_level
|
|
1
|
+
from .load import load_format, load_level
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
import glob
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
from amulet_nbt import load as load_nbt
|
|
6
|
-
|
|
7
|
-
from .anvil_world import AnvilFormat
|
|
8
|
-
from amulet.utils.format_utils import check_all_exist
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class AnvilForgeFormat(AnvilFormat):
|
|
12
|
-
"""
|
|
13
|
-
This FormatWrapper class is a modification on the :class:`AnvilFormat` class that separates Forge worlds from vanilla worlds.
|
|
14
|
-
|
|
15
|
-
Currently there is no extra logic here but this should extend the :class:`AnvilFormat` class to support Forge worlds.
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
@staticmethod
|
|
19
|
-
def is_valid(path: str) -> bool:
|
|
20
|
-
if not check_all_exist(path, "level.dat"):
|
|
21
|
-
return False
|
|
22
|
-
|
|
23
|
-
try:
|
|
24
|
-
level_dat_root = load_nbt(os.path.join(path, "level.dat")).compound
|
|
25
|
-
except:
|
|
26
|
-
return False
|
|
27
|
-
|
|
28
|
-
return "Data" in level_dat_root and (
|
|
29
|
-
"FML" in level_dat_root or "fml" in level_dat_root
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
@property
|
|
33
|
-
def game_version_string(self) -> str:
|
|
34
|
-
try:
|
|
35
|
-
return f'Java Forge {self.root_tag.compound.get_compound("Data").get_compound("Version").get_string("Name").py_str}'
|
|
36
|
-
except Exception:
|
|
37
|
-
return f"Java Forge Unknown Version"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
export = AnvilForgeFormat
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import glob
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
from amulet_nbt import load as load_nbt
|
|
6
|
+
|
|
7
|
+
from .anvil_world import AnvilFormat
|
|
8
|
+
from amulet.utils.format_utils import check_all_exist
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AnvilForgeFormat(AnvilFormat):
|
|
12
|
+
"""
|
|
13
|
+
This FormatWrapper class is a modification on the :class:`AnvilFormat` class that separates Forge worlds from vanilla worlds.
|
|
14
|
+
|
|
15
|
+
Currently there is no extra logic here but this should extend the :class:`AnvilFormat` class to support Forge worlds.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def is_valid(path: str) -> bool:
|
|
20
|
+
if not check_all_exist(path, "level.dat"):
|
|
21
|
+
return False
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
level_dat_root = load_nbt(os.path.join(path, "level.dat")).compound
|
|
25
|
+
except:
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
return "Data" in level_dat_root and (
|
|
29
|
+
"FML" in level_dat_root or "fml" in level_dat_root
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def game_version_string(self) -> str:
|
|
34
|
+
try:
|
|
35
|
+
return f'Java Forge {self.root_tag.compound.get_compound("Data").get_compound("Version").get_string("Name").py_str}'
|
|
36
|
+
except Exception:
|
|
37
|
+
return f"Java Forge Unknown Version"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
export = AnvilForgeFormat
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .format import AnvilFormat
|
|
2
|
-
|
|
3
|
-
export = AnvilFormat
|
|
1
|
+
from .format import AnvilFormat
|
|
2
|
+
|
|
3
|
+
export = AnvilFormat
|