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.

Files changed (198) hide show
  1. amulet/__init__.py +27 -27
  2. amulet/__pyinstaller/__init__.py +2 -2
  3. amulet/__pyinstaller/hook-amulet.py +4 -4
  4. amulet/_version.py +21 -21
  5. amulet/api/__init__.py +2 -2
  6. amulet/api/abstract_base_entity.py +128 -128
  7. amulet/api/block.py +630 -630
  8. amulet/api/block_entity.py +71 -71
  9. amulet/api/cache.py +107 -107
  10. amulet/api/chunk/__init__.py +6 -6
  11. amulet/api/chunk/biomes.py +207 -207
  12. amulet/api/chunk/block_entity_dict.py +175 -175
  13. amulet/api/chunk/blocks.py +46 -46
  14. amulet/api/chunk/chunk.py +389 -389
  15. amulet/api/chunk/entity_list.py +75 -75
  16. amulet/api/chunk/status.py +167 -167
  17. amulet/api/data_types/__init__.py +4 -4
  18. amulet/api/data_types/generic_types.py +4 -4
  19. amulet/api/data_types/operation_types.py +16 -16
  20. amulet/api/data_types/world_types.py +49 -49
  21. amulet/api/data_types/wrapper_types.py +71 -71
  22. amulet/api/entity.py +74 -74
  23. amulet/api/errors.py +119 -119
  24. amulet/api/history/__init__.py +36 -36
  25. amulet/api/history/base/__init__.py +3 -3
  26. amulet/api/history/base/base_history.py +26 -26
  27. amulet/api/history/base/history_manager.py +63 -63
  28. amulet/api/history/base/revision_manager.py +73 -73
  29. amulet/api/history/changeable.py +15 -15
  30. amulet/api/history/data_types.py +7 -7
  31. amulet/api/history/history_manager/__init__.py +3 -3
  32. amulet/api/history/history_manager/container.py +102 -102
  33. amulet/api/history/history_manager/database.py +279 -279
  34. amulet/api/history/history_manager/meta.py +93 -93
  35. amulet/api/history/history_manager/object.py +116 -116
  36. amulet/api/history/revision_manager/__init__.py +2 -2
  37. amulet/api/history/revision_manager/disk.py +33 -33
  38. amulet/api/history/revision_manager/ram.py +12 -12
  39. amulet/api/item.py +75 -75
  40. amulet/api/level/__init__.py +4 -4
  41. amulet/api/level/base_level/__init__.py +1 -1
  42. amulet/api/level/base_level/base_level.py +1035 -1026
  43. amulet/api/level/base_level/chunk_manager.py +227 -227
  44. amulet/api/level/base_level/clone.py +389 -389
  45. amulet/api/level/base_level/player_manager.py +101 -101
  46. amulet/api/level/immutable_structure/__init__.py +1 -1
  47. amulet/api/level/immutable_structure/immutable_structure.py +94 -94
  48. amulet/api/level/immutable_structure/void_format_wrapper.py +117 -117
  49. amulet/api/level/structure.py +22 -22
  50. amulet/api/level/world.py +19 -19
  51. amulet/api/partial_3d_array/__init__.py +2 -2
  52. amulet/api/partial_3d_array/base_partial_3d_array.py +263 -263
  53. amulet/api/partial_3d_array/bounded_partial_3d_array.py +528 -528
  54. amulet/api/partial_3d_array/data_types.py +15 -15
  55. amulet/api/partial_3d_array/unbounded_partial_3d_array.py +229 -229
  56. amulet/api/partial_3d_array/util.py +152 -152
  57. amulet/api/player.py +65 -65
  58. amulet/api/registry/__init__.py +2 -2
  59. amulet/api/registry/base_registry.py +34 -34
  60. amulet/api/registry/biome_manager.py +153 -153
  61. amulet/api/registry/block_manager.py +156 -156
  62. amulet/api/selection/__init__.py +2 -2
  63. amulet/api/selection/abstract_selection.py +315 -315
  64. amulet/api/selection/box.py +805 -805
  65. amulet/api/selection/group.py +488 -488
  66. amulet/api/structure.py +37 -37
  67. amulet/api/wrapper/__init__.py +8 -8
  68. amulet/api/wrapper/chunk/interface.py +441 -441
  69. amulet/api/wrapper/chunk/translator.py +567 -567
  70. amulet/api/wrapper/format_wrapper.py +772 -772
  71. amulet/api/wrapper/structure_format_wrapper.py +116 -116
  72. amulet/api/wrapper/world_format_wrapper.py +63 -63
  73. amulet/level/__init__.py +1 -1
  74. amulet/level/formats/anvil_forge_world.py +40 -40
  75. amulet/level/formats/anvil_world/__init__.py +3 -3
  76. amulet/level/formats/anvil_world/_sector_manager.py +291 -384
  77. amulet/level/formats/anvil_world/data_pack/__init__.py +2 -2
  78. amulet/level/formats/anvil_world/data_pack/data_pack.py +224 -224
  79. amulet/level/formats/anvil_world/data_pack/data_pack_manager.py +77 -77
  80. amulet/level/formats/anvil_world/dimension.py +177 -177
  81. amulet/level/formats/anvil_world/format.py +769 -769
  82. amulet/level/formats/anvil_world/region.py +384 -384
  83. amulet/level/formats/construction/__init__.py +3 -3
  84. amulet/level/formats/construction/format_wrapper.py +515 -515
  85. amulet/level/formats/construction/interface.py +134 -134
  86. amulet/level/formats/construction/section.py +60 -60
  87. amulet/level/formats/construction/util.py +165 -165
  88. amulet/level/formats/leveldb_world/__init__.py +3 -3
  89. amulet/level/formats/leveldb_world/chunk.py +33 -33
  90. amulet/level/formats/leveldb_world/dimension.py +385 -419
  91. amulet/level/formats/leveldb_world/format.py +659 -641
  92. amulet/level/formats/leveldb_world/interface/chunk/__init__.py +36 -36
  93. amulet/level/formats/leveldb_world/interface/chunk/base_leveldb_interface.py +836 -836
  94. amulet/level/formats/leveldb_world/interface/chunk/generate_interface.py +31 -31
  95. amulet/level/formats/leveldb_world/interface/chunk/leveldb_0.py +30 -30
  96. amulet/level/formats/leveldb_world/interface/chunk/leveldb_1.py +12 -12
  97. amulet/level/formats/leveldb_world/interface/chunk/leveldb_10.py +12 -12
  98. amulet/level/formats/leveldb_world/interface/chunk/leveldb_11.py +12 -12
  99. amulet/level/formats/leveldb_world/interface/chunk/leveldb_12.py +12 -12
  100. amulet/level/formats/leveldb_world/interface/chunk/leveldb_13.py +12 -12
  101. amulet/level/formats/leveldb_world/interface/chunk/leveldb_14.py +12 -12
  102. amulet/level/formats/leveldb_world/interface/chunk/leveldb_15.py +12 -12
  103. amulet/level/formats/leveldb_world/interface/chunk/leveldb_16.py +12 -12
  104. amulet/level/formats/leveldb_world/interface/chunk/leveldb_17.py +12 -12
  105. amulet/level/formats/leveldb_world/interface/chunk/leveldb_18.py +12 -12
  106. amulet/level/formats/leveldb_world/interface/chunk/leveldb_19.py +12 -12
  107. amulet/level/formats/leveldb_world/interface/chunk/leveldb_2.py +12 -12
  108. amulet/level/formats/leveldb_world/interface/chunk/leveldb_20.py +12 -12
  109. amulet/level/formats/leveldb_world/interface/chunk/leveldb_21.py +12 -12
  110. amulet/level/formats/leveldb_world/interface/chunk/leveldb_22.py +12 -12
  111. amulet/level/formats/leveldb_world/interface/chunk/leveldb_23.py +10 -10
  112. amulet/level/formats/leveldb_world/interface/chunk/leveldb_24.py +10 -10
  113. amulet/level/formats/leveldb_world/interface/chunk/leveldb_25.py +24 -24
  114. amulet/level/formats/leveldb_world/interface/chunk/leveldb_26.py +10 -10
  115. amulet/level/formats/leveldb_world/interface/chunk/leveldb_27.py +10 -10
  116. amulet/level/formats/leveldb_world/interface/chunk/leveldb_28.py +10 -10
  117. amulet/level/formats/leveldb_world/interface/chunk/leveldb_29.py +33 -33
  118. amulet/level/formats/leveldb_world/interface/chunk/leveldb_3.py +57 -57
  119. amulet/level/formats/leveldb_world/interface/chunk/leveldb_30.py +10 -10
  120. amulet/level/formats/leveldb_world/interface/chunk/leveldb_31.py +10 -10
  121. amulet/level/formats/leveldb_world/interface/chunk/leveldb_32.py +10 -10
  122. amulet/level/formats/leveldb_world/interface/chunk/leveldb_33.py +10 -10
  123. amulet/level/formats/leveldb_world/interface/chunk/leveldb_34.py +10 -10
  124. amulet/level/formats/leveldb_world/interface/chunk/leveldb_35.py +10 -10
  125. amulet/level/formats/leveldb_world/interface/chunk/leveldb_36.py +10 -10
  126. amulet/level/formats/leveldb_world/interface/chunk/leveldb_37.py +10 -10
  127. amulet/level/formats/leveldb_world/interface/chunk/leveldb_38.py +10 -10
  128. amulet/level/formats/leveldb_world/interface/chunk/leveldb_39.py +12 -12
  129. amulet/level/formats/leveldb_world/interface/chunk/leveldb_4.py +12 -12
  130. amulet/level/formats/leveldb_world/interface/chunk/leveldb_40.py +16 -16
  131. amulet/level/formats/leveldb_world/interface/chunk/leveldb_5.py +12 -12
  132. amulet/level/formats/leveldb_world/interface/chunk/leveldb_6.py +12 -12
  133. amulet/level/formats/leveldb_world/interface/chunk/leveldb_7.py +12 -12
  134. amulet/level/formats/leveldb_world/interface/chunk/leveldb_8.py +180 -180
  135. amulet/level/formats/leveldb_world/interface/chunk/leveldb_9.py +18 -18
  136. amulet/level/formats/leveldb_world/interface/chunk/leveldb_chunk_versions.py +79 -79
  137. amulet/level/formats/mcstructure/__init__.py +3 -3
  138. amulet/level/formats/mcstructure/chunk.py +50 -50
  139. amulet/level/formats/mcstructure/format_wrapper.py +408 -408
  140. amulet/level/formats/mcstructure/interface.py +175 -175
  141. amulet/level/formats/schematic/__init__.py +3 -3
  142. amulet/level/formats/schematic/chunk.py +55 -55
  143. amulet/level/formats/schematic/data_types.py +4 -4
  144. amulet/level/formats/schematic/format_wrapper.py +373 -373
  145. amulet/level/formats/schematic/interface.py +142 -142
  146. amulet/level/formats/sponge_schem/__init__.py +4 -4
  147. amulet/level/formats/sponge_schem/chunk.py +62 -62
  148. amulet/level/formats/sponge_schem/format_wrapper.py +463 -463
  149. amulet/level/formats/sponge_schem/interface.py +118 -118
  150. amulet/level/formats/sponge_schem/varint/__init__.py +1 -1
  151. amulet/level/formats/sponge_schem/varint/varint.py +87 -87
  152. amulet/level/interfaces/chunk/anvil/anvil_0.py +72 -72
  153. amulet/level/interfaces/chunk/anvil/anvil_1444.py +336 -336
  154. amulet/level/interfaces/chunk/anvil/anvil_1466.py +94 -94
  155. amulet/level/interfaces/chunk/anvil/anvil_1467.py +37 -37
  156. amulet/level/interfaces/chunk/anvil/anvil_1484.py +20 -20
  157. amulet/level/interfaces/chunk/anvil/anvil_1503.py +20 -20
  158. amulet/level/interfaces/chunk/anvil/anvil_1519.py +34 -34
  159. amulet/level/interfaces/chunk/anvil/anvil_1901.py +20 -20
  160. amulet/level/interfaces/chunk/anvil/anvil_1908.py +20 -20
  161. amulet/level/interfaces/chunk/anvil/anvil_1912.py +21 -21
  162. amulet/level/interfaces/chunk/anvil/anvil_1934.py +20 -20
  163. amulet/level/interfaces/chunk/anvil/anvil_2203.py +69 -69
  164. amulet/level/interfaces/chunk/anvil/anvil_2529.py +19 -19
  165. amulet/level/interfaces/chunk/anvil/anvil_2681.py +76 -76
  166. amulet/level/interfaces/chunk/anvil/anvil_2709.py +19 -19
  167. amulet/level/interfaces/chunk/anvil/anvil_2844.py +267 -267
  168. amulet/level/interfaces/chunk/anvil/anvil_3463.py +19 -19
  169. amulet/level/interfaces/chunk/anvil/anvil_na.py +607 -607
  170. amulet/level/interfaces/chunk/anvil/base_anvil_interface.py +326 -326
  171. amulet/level/load.py +59 -59
  172. amulet/level/loader.py +95 -95
  173. amulet/level/translators/chunk/bedrock/__init__.py +267 -267
  174. amulet/level/translators/chunk/bedrock/bedrock_nbt_blockstate_translator.py +46 -46
  175. amulet/level/translators/chunk/bedrock/bedrock_numerical_translator.py +39 -39
  176. amulet/level/translators/chunk/bedrock/bedrock_psudo_numerical_translator.py +37 -37
  177. amulet/level/translators/chunk/java/java_1_18_translator.py +40 -40
  178. amulet/level/translators/chunk/java/java_blockstate_translator.py +94 -94
  179. amulet/level/translators/chunk/java/java_numerical_translator.py +62 -62
  180. amulet/libs/leveldb/__init__.py +7 -7
  181. amulet/operations/__init__.py +5 -5
  182. amulet/operations/clone.py +18 -18
  183. amulet/operations/delete_chunk.py +32 -32
  184. amulet/operations/fill.py +30 -30
  185. amulet/operations/paste.py +65 -65
  186. amulet/operations/replace.py +58 -58
  187. amulet/utils/__init__.py +14 -14
  188. amulet/utils/format_utils.py +41 -41
  189. amulet/utils/generator.py +15 -15
  190. amulet/utils/matrix.py +243 -243
  191. amulet/utils/numpy_helpers.py +46 -46
  192. amulet/utils/world_utils.py +349 -349
  193. {amulet_core-1.9.19.dist-info → amulet_core-1.9.20.dist-info}/METADATA +97 -97
  194. amulet_core-1.9.20.dist-info/RECORD +208 -0
  195. amulet_core-1.9.19.dist-info/RECORD +0 -208
  196. {amulet_core-1.9.19.dist-info → amulet_core-1.9.20.dist-info}/WHEEL +0 -0
  197. {amulet_core-1.9.19.dist-info → amulet_core-1.9.20.dist-info}/entry_points.txt +0 -0
  198. {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