amulet-core 2.0a8__cp312-cp312-win_amd64.whl → 2.0.1a3.post250529101330__cp312-cp312-win_amd64.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 (271) hide show
  1. amulet/core/__init__.py +36 -0
  2. amulet/core/__pyinstaller/hook-amulet.core.py +4 -0
  3. amulet/core/_amulet_core.cp312-win_amd64.pyd +0 -0
  4. amulet/core/_amulet_core.pyi +7 -0
  5. amulet/{_version.py → core/_version.py} +3 -3
  6. amulet/core/amulet_core.dll +0 -0
  7. amulet/core/amulet_core.lib +0 -0
  8. amulet/core/amulet_coreConfig.cmake +18 -0
  9. amulet/{biome.pyi → core/biome/__init__.pyi} +3 -3
  10. amulet/core/biome/biome.hpp +53 -0
  11. amulet/{block.pyi → core/block/__init__.pyi} +25 -26
  12. amulet/core/block/block.hpp +156 -0
  13. amulet/{block_entity.pyi → core/block_entity/__init__.pyi} +7 -7
  14. amulet/core/block_entity/block_entity.hpp +84 -0
  15. amulet/{errors.py → core/chunk/__init__.pyi} +37 -33
  16. amulet/core/chunk/chunk.hpp +126 -0
  17. amulet/core/chunk/component/__init__.pyi +18 -0
  18. amulet/core/chunk/component/biome_3d_component.hpp +96 -0
  19. amulet/core/chunk/component/block_component.hpp +101 -0
  20. amulet/core/chunk/component/block_component.pyi +28 -0
  21. amulet/core/chunk/component/block_entity_component.hpp +119 -0
  22. amulet/core/chunk/component/section_array_map.hpp +129 -0
  23. amulet/{chunk_components.pyi → core/chunk/component/section_array_map.pyi} +4 -24
  24. amulet/core/dll.hpp +21 -0
  25. amulet/core/entity/__init__.pyi +105 -0
  26. amulet/core/entity/entity.hpp +100 -0
  27. amulet/{palette → core/palette}/__init__.pyi +2 -2
  28. amulet/core/palette/biome_palette.hpp +65 -0
  29. amulet/{palette → core/palette}/biome_palette.pyi +8 -8
  30. amulet/core/palette/block_palette.hpp +71 -0
  31. amulet/{palette → core/palette}/block_palette.pyi +12 -10
  32. amulet/core/selection/__init__.pyi +8 -0
  33. amulet/core/selection/box.hpp +86 -0
  34. amulet/core/selection/box.pyi +215 -0
  35. amulet/core/selection/group.hpp +80 -0
  36. amulet/core/selection/group.pyi +213 -0
  37. amulet/{version.pyi → core/version/__init__.pyi} +58 -10
  38. amulet/core/version/version.hpp +204 -0
  39. {amulet_core-2.0a8.dist-info → amulet_core-2.0.1a3.post250529101330.dist-info}/METADATA +25 -20
  40. amulet_core-2.0.1a3.post250529101330.dist-info/RECORD +45 -0
  41. {amulet_core-2.0a8.dist-info → amulet_core-2.0.1a3.post250529101330.dist-info}/WHEEL +1 -1
  42. amulet_core-2.0.1a3.post250529101330.dist-info/entry_points.txt +2 -0
  43. amulet/__init__.cp312-win_amd64.pyd +0 -0
  44. amulet/__init__.py.cpp +0 -45
  45. amulet/__init__.pyi +0 -30
  46. amulet/__pyinstaller/hook-amulet.py +0 -4
  47. amulet/_init.py +0 -26
  48. amulet/biome.cpp +0 -36
  49. amulet/biome.hpp +0 -43
  50. amulet/biome.py.cpp +0 -122
  51. amulet/block.cpp +0 -435
  52. amulet/block.hpp +0 -119
  53. amulet/block.py.cpp +0 -377
  54. amulet/block_entity.cpp +0 -12
  55. amulet/block_entity.hpp +0 -56
  56. amulet/block_entity.py.cpp +0 -115
  57. amulet/chunk.cpp +0 -16
  58. amulet/chunk.hpp +0 -100
  59. amulet/chunk.py.cpp +0 -80
  60. amulet/chunk.pyi +0 -28
  61. amulet/chunk_components/biome_3d_component.cpp +0 -5
  62. amulet/chunk_components/biome_3d_component.hpp +0 -79
  63. amulet/chunk_components/block_component.cpp +0 -41
  64. amulet/chunk_components/block_component.hpp +0 -88
  65. amulet/chunk_components/block_entity_component.cpp +0 -5
  66. amulet/chunk_components/block_entity_component.hpp +0 -147
  67. amulet/chunk_components/section_array_map.cpp +0 -129
  68. amulet/chunk_components/section_array_map.hpp +0 -147
  69. amulet/collections/eq.py.hpp +0 -37
  70. amulet/collections/hash.py.hpp +0 -27
  71. amulet/collections/holder.py.hpp +0 -37
  72. amulet/collections/iterator.py.hpp +0 -80
  73. amulet/collections/mapping.py.hpp +0 -199
  74. amulet/collections/mutable_mapping.py.hpp +0 -226
  75. amulet/collections/sequence.py.hpp +0 -163
  76. amulet/collections.pyi +0 -40
  77. amulet/data_types.py +0 -29
  78. amulet/entity.py +0 -182
  79. amulet/game/__init__.py +0 -7
  80. amulet/game/_game.py +0 -152
  81. amulet/game/_universal/__init__.py +0 -1
  82. amulet/game/_universal/_biome.py +0 -17
  83. amulet/game/_universal/_block.py +0 -47
  84. amulet/game/_universal/_version.py +0 -68
  85. amulet/game/abc/__init__.py +0 -22
  86. amulet/game/abc/_block_specification.py +0 -150
  87. amulet/game/abc/biome.py +0 -213
  88. amulet/game/abc/block.py +0 -331
  89. amulet/game/abc/game_version_container.py +0 -25
  90. amulet/game/abc/json_interface.py +0 -27
  91. amulet/game/abc/version.py +0 -44
  92. amulet/game/bedrock/__init__.py +0 -1
  93. amulet/game/bedrock/_biome.py +0 -35
  94. amulet/game/bedrock/_block.py +0 -42
  95. amulet/game/bedrock/_version.py +0 -165
  96. amulet/game/java/__init__.py +0 -2
  97. amulet/game/java/_biome.py +0 -35
  98. amulet/game/java/_block.py +0 -60
  99. amulet/game/java/_version.py +0 -176
  100. amulet/game/translate/__init__.py +0 -12
  101. amulet/game/translate/_functions/__init__.py +0 -15
  102. amulet/game/translate/_functions/_code_functions/__init__.py +0 -0
  103. amulet/game/translate/_functions/_code_functions/_text.py +0 -553
  104. amulet/game/translate/_functions/_code_functions/banner_pattern.py +0 -67
  105. amulet/game/translate/_functions/_code_functions/bedrock_chest_connection.py +0 -152
  106. amulet/game/translate/_functions/_code_functions/bedrock_moving_block_pos.py +0 -88
  107. amulet/game/translate/_functions/_code_functions/bedrock_sign.py +0 -152
  108. amulet/game/translate/_functions/_code_functions/bedrock_skull_rotation.py +0 -16
  109. amulet/game/translate/_functions/_code_functions/custom_name.py +0 -146
  110. amulet/game/translate/_functions/_frozen.py +0 -66
  111. amulet/game/translate/_functions/_state.py +0 -54
  112. amulet/game/translate/_functions/_typing.py +0 -98
  113. amulet/game/translate/_functions/abc.py +0 -123
  114. amulet/game/translate/_functions/carry_nbt.py +0 -160
  115. amulet/game/translate/_functions/carry_properties.py +0 -80
  116. amulet/game/translate/_functions/code.py +0 -143
  117. amulet/game/translate/_functions/map_block_name.py +0 -66
  118. amulet/game/translate/_functions/map_nbt.py +0 -111
  119. amulet/game/translate/_functions/map_properties.py +0 -93
  120. amulet/game/translate/_functions/multiblock.py +0 -112
  121. amulet/game/translate/_functions/new_block.py +0 -42
  122. amulet/game/translate/_functions/new_entity.py +0 -43
  123. amulet/game/translate/_functions/new_nbt.py +0 -206
  124. amulet/game/translate/_functions/new_properties.py +0 -64
  125. amulet/game/translate/_functions/sequence.py +0 -51
  126. amulet/game/translate/_functions/walk_input_nbt.py +0 -331
  127. amulet/game/translate/_translator.py +0 -433
  128. amulet/img/__init__.py +0 -10
  129. amulet/img/missing_no.png +0 -0
  130. amulet/img/missing_pack.png +0 -0
  131. amulet/img/missing_world.png +0 -0
  132. amulet/io/binary_reader.hpp +0 -45
  133. amulet/io/binary_writer.hpp +0 -30
  134. amulet/item.py +0 -75
  135. amulet/level/__init__.pyi +0 -23
  136. amulet/level/_load.py +0 -100
  137. amulet/level/abc/__init__.py +0 -12
  138. amulet/level/abc/_chunk_handle.py +0 -358
  139. amulet/level/abc/_dimension.py +0 -86
  140. amulet/level/abc/_history/__init__.py +0 -1
  141. amulet/level/abc/_history/_cache.py +0 -224
  142. amulet/level/abc/_history/_history_manager.py +0 -291
  143. amulet/level/abc/_level/__init__.py +0 -5
  144. amulet/level/abc/_level/_compactable_level.py +0 -10
  145. amulet/level/abc/_level/_creatable_level.py +0 -28
  146. amulet/level/abc/_level/_disk_level.py +0 -17
  147. amulet/level/abc/_level/_level.py +0 -449
  148. amulet/level/abc/_level/_loadable_level.py +0 -42
  149. amulet/level/abc/_player_storage.py +0 -7
  150. amulet/level/abc/_raw_level.py +0 -187
  151. amulet/level/abc/_registry.py +0 -40
  152. amulet/level/java/__init__.pyi +0 -16
  153. amulet/level/java/_chunk_handle.py +0 -17
  154. amulet/level/java/_dimension.py +0 -20
  155. amulet/level/java/_level.py +0 -184
  156. amulet/level/java/_raw/__init__.pyi +0 -15
  157. amulet/level/java/_raw/_chunk.pyi +0 -23
  158. amulet/level/java/_raw/_constant.py +0 -9
  159. amulet/level/java/_raw/_data_pack/__init__.py +0 -2
  160. amulet/level/java/_raw/_data_pack/data_pack.py +0 -241
  161. amulet/level/java/_raw/_data_pack/data_pack_manager.py +0 -77
  162. amulet/level/java/_raw/_dimension.py +0 -86
  163. amulet/level/java/_raw/_level.py +0 -507
  164. amulet/level/java/_raw/_typing.py +0 -3
  165. amulet/level/java/_raw/java_chunk_decode.cpp +0 -531
  166. amulet/level/java/_raw/java_chunk_decode.hpp +0 -23
  167. amulet/level/java/_raw/java_chunk_encode.cpp +0 -25
  168. amulet/level/java/_raw/java_chunk_encode.hpp +0 -23
  169. amulet/level/java/anvil/__init__.py +0 -2
  170. amulet/level/java/anvil/_dimension.py +0 -170
  171. amulet/level/java/anvil/_region.py +0 -421
  172. amulet/level/java/anvil/_sector_manager.py +0 -223
  173. amulet/level/java/chunk.pyi +0 -81
  174. amulet/level/java/chunk_/_chunk.py +0 -260
  175. amulet/level/java/chunk_/components/inhabited_time.py +0 -12
  176. amulet/level/java/chunk_/components/last_update.py +0 -12
  177. amulet/level/java/chunk_/components/legacy_version.py +0 -12
  178. amulet/level/java/chunk_/components/light_populated.py +0 -12
  179. amulet/level/java/chunk_/components/named_height_2d.py +0 -37
  180. amulet/level/java/chunk_/components/status.py +0 -11
  181. amulet/level/java/chunk_/components/terrain_populated.py +0 -12
  182. amulet/level/java/chunk_components/data_version_component.cpp +0 -32
  183. amulet/level/java/chunk_components/data_version_component.hpp +0 -31
  184. amulet/level/java/chunk_components/java_raw_chunk_component.cpp +0 -56
  185. amulet/level/java/chunk_components/java_raw_chunk_component.hpp +0 -45
  186. amulet/level/java/chunk_components.pyi +0 -22
  187. amulet/level/java/java_chunk.cpp +0 -170
  188. amulet/level/java/java_chunk.hpp +0 -141
  189. amulet/level/java/long_array.hpp +0 -175
  190. amulet/level/java/long_array.pyi +0 -39
  191. amulet/level/temporary_level/__init__.py +0 -1
  192. amulet/level/temporary_level/_level.py +0 -16
  193. amulet/mesh/__init__.py +0 -0
  194. amulet/mesh/block/__init__.pyi +0 -301
  195. amulet/mesh/block/_cube.py +0 -198
  196. amulet/mesh/block/_missing_block.py +0 -20
  197. amulet/mesh/block/block_mesh.cpp +0 -107
  198. amulet/mesh/block/block_mesh.hpp +0 -207
  199. amulet/mesh/util.py +0 -17
  200. amulet/palette/biome_palette.hpp +0 -85
  201. amulet/palette/block_palette.cpp +0 -32
  202. amulet/palette/block_palette.hpp +0 -93
  203. amulet/player.py +0 -62
  204. amulet/pybind11/collections.hpp +0 -118
  205. amulet/pybind11/numpy.hpp +0 -26
  206. amulet/pybind11/py_module.hpp +0 -34
  207. amulet/pybind11/type_hints.hpp +0 -51
  208. amulet/pybind11/types.hpp +0 -25
  209. amulet/pybind11/typing.hpp +0 -7
  210. amulet/resource_pack/__init__.py +0 -63
  211. amulet/resource_pack/abc/__init__.py +0 -2
  212. amulet/resource_pack/abc/resource_pack.py +0 -38
  213. amulet/resource_pack/abc/resource_pack_manager.py +0 -85
  214. amulet/resource_pack/java/__init__.py +0 -2
  215. amulet/resource_pack/java/download_resources.py +0 -212
  216. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_black.png +0 -0
  217. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_blue.png +0 -0
  218. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_brown.png +0 -0
  219. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_cyan.png +0 -0
  220. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_gray.png +0 -0
  221. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_green.png +0 -0
  222. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_light_blue.png +0 -0
  223. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_light_gray.png +0 -0
  224. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_lime.png +0 -0
  225. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_magenta.png +0 -0
  226. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_orange.png +0 -0
  227. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_pink.png +0 -0
  228. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_purple.png +0 -0
  229. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_red.png +0 -0
  230. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_white.png +0 -0
  231. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_yellow.png +0 -0
  232. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/barrier.png +0 -0
  233. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/end_portal.png +0 -0
  234. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/grass.png +0 -0
  235. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/lava.png +0 -0
  236. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/structure_void.png +0 -0
  237. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water.png +0 -0
  238. amulet/resource_pack/java/java_vanilla_fix/pack.png +0 -0
  239. amulet/resource_pack/java/resource_pack.py +0 -44
  240. amulet/resource_pack/java/resource_pack_manager.py +0 -563
  241. amulet/resource_pack/unknown_resource_pack.py +0 -10
  242. amulet/selection/__init__.py +0 -2
  243. amulet/selection/abstract_selection.py +0 -342
  244. amulet/selection/box.py +0 -852
  245. amulet/selection/group.py +0 -481
  246. amulet/utils/__init__.pyi +0 -23
  247. amulet/utils/call_spec/__init__.py +0 -24
  248. amulet/utils/call_spec/_call_spec.py +0 -257
  249. amulet/utils/cast.py +0 -10
  250. amulet/utils/comment_json.py +0 -188
  251. amulet/utils/format_utils.py +0 -41
  252. amulet/utils/generator.py +0 -18
  253. amulet/utils/matrix.py +0 -243
  254. amulet/utils/numpy.hpp +0 -36
  255. amulet/utils/numpy.pyi +0 -11
  256. amulet/utils/numpy_helpers.py +0 -19
  257. amulet/utils/shareable_lock.py +0 -335
  258. amulet/utils/signal/__init__.py +0 -10
  259. amulet/utils/signal/_signal.py +0 -228
  260. amulet/utils/task_manager.py +0 -235
  261. amulet/utils/typed_property.py +0 -111
  262. amulet/utils/weakref.py +0 -70
  263. amulet/utils/world_utils.py +0 -102
  264. amulet/version.cpp +0 -136
  265. amulet/version.hpp +0 -142
  266. amulet/version.py.cpp +0 -281
  267. amulet_core-2.0a8.dist-info/RECORD +0 -241
  268. amulet_core-2.0a8.dist-info/entry_points.txt +0 -2
  269. /amulet/{__pyinstaller → core/__pyinstaller}/__init__.py +0 -0
  270. /amulet/{py.typed → core/py.typed} +0 -0
  271. {amulet_core-2.0a8.dist-info → amulet_core-2.0.1a3.post250529101330.dist-info}/top_level.txt +0 -0
@@ -1,449 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from abc import ABC, abstractmethod
4
- from typing import TYPE_CHECKING, Optional, TypeVar, Type, Generic, Iterator, Callable
5
- from contextlib import contextmanager, AbstractContextManager as ContextManager
6
- import logging
7
- from weakref import finalize
8
-
9
- from runtime_final import final
10
- from PIL import Image
11
-
12
- from amulet.version import PlatformType, VersionNumber
13
- from amulet.data_types import DimensionId
14
- from amulet.img import missing_world_icon_path
15
-
16
- from amulet.chunk import Chunk
17
-
18
- from amulet.utils.shareable_lock import ShareableRLock
19
- from amulet.utils.signal import Signal, SignalInstanceCacheName
20
- from amulet.utils.task_manager import AbstractCancelManager, VoidCancelManager
21
-
22
- from amulet.level.abc._history import HistoryManager
23
- from amulet.utils.weakref import CallableWeakMethod
24
-
25
-
26
- if TYPE_CHECKING:
27
- from amulet.level.abc import Dimension # noqa
28
- from amulet.level.abc import PlayerStorage
29
- from amulet.level.abc import RawLevel # noqa
30
-
31
- log = logging.getLogger(__name__)
32
-
33
- missing_world_icon: Optional[Image.Image] = None
34
-
35
-
36
- RawLevelT = TypeVar("RawLevelT", bound="RawLevel")
37
- DimensionT = TypeVar("DimensionT", bound="Dimension")
38
-
39
-
40
- class LevelOpenData:
41
- """Private level attributes that only exist when the level is open."""
42
-
43
- history_manager: HistoryManager
44
-
45
- def __init__(self) -> None:
46
- self.history_manager = HistoryManager()
47
-
48
-
49
- OpenLevelDataT = TypeVar("OpenLevelDataT", bound=LevelOpenData)
50
-
51
-
52
- class Level(ABC, Generic[OpenLevelDataT, DimensionT, RawLevelT]):
53
- """Base class for all levels."""
54
-
55
- __finalise: finalize
56
- _open_data: OpenLevelDataT | None
57
- _level_lock: ShareableRLock
58
- _history_enabled: bool
59
-
60
- __slots__ = (
61
- "__weakref__",
62
- "__finalise",
63
- SignalInstanceCacheName,
64
- "_open_data",
65
- "_level_lock",
66
- "_history_enabled",
67
- )
68
-
69
- def __init__(self) -> None:
70
- """
71
- This cannot be called directly.
72
- You must use one of the constructor classmethods
73
- """
74
- # Private attributes
75
- self._open_data = None
76
- self._level_lock = ShareableRLock()
77
- self._history_enabled = True
78
- self.__finalise = finalize(self, CallableWeakMethod(self.close))
79
-
80
- def __del__(self) -> None:
81
- self.__finalise()
82
-
83
- opened = Signal[()]()
84
-
85
- @final
86
- def open(self, task_manager: AbstractCancelManager = VoidCancelManager()) -> None:
87
- """Open the level.
88
-
89
- If the level is already open, this does nothing.
90
-
91
- :param task_manager: The cancel manager through which cancel can be requested.
92
- :raises amulet.utils.task_manager.TaskCancelled: If the task is cancelled.
93
- """
94
- with self.lock_unique(task_manager=task_manager):
95
- if self.is_open(task_manager=task_manager):
96
- # Do nothing if already open
97
- return
98
- self._open()
99
- if self._open_data is None:
100
- raise RuntimeError("_open_data has not been set")
101
- self._open_data.history_manager.history_changed.connect(
102
- self.history_changed
103
- )
104
- self.opened.emit()
105
-
106
- @abstractmethod
107
- def _open(self) -> None:
108
- raise NotImplementedError
109
-
110
- @final
111
- def is_open(
112
- self, task_manager: AbstractCancelManager = VoidCancelManager()
113
- ) -> bool:
114
- """Has the level been opened.
115
-
116
- :param task_manager: The cancel manager through which cancel can be requested.
117
- :return: True if the level is open otherwise False.
118
- :raises amulet.utils.task_manager.TaskCancelled: If the task is cancelled.
119
- """
120
- with self.lock_shared(task_manager=task_manager):
121
- return self._open_data is not None
122
-
123
- @final
124
- @property
125
- def _o(self) -> OpenLevelDataT:
126
- o = self._open_data
127
- if o is None:
128
- raise RuntimeError("Level is not open")
129
- return o
130
-
131
- # Has the internal state changed
132
- changed = Signal[()]()
133
- # Has the external state been changed without our knowledge
134
- external_changed = Signal[()]()
135
-
136
- @abstractmethod
137
- def save(self) -> None:
138
- raise NotImplementedError
139
-
140
- # Signal to notify all listeners that the data they hold is no longer valid
141
- purged = Signal[()]()
142
-
143
- def purge(self) -> None:
144
- """
145
- Unload all loaded data.
146
- This is a nuclear function and must be used with :meth:`lock_unique`
147
-
148
- This is functionally the same as closing and reopening the level.
149
- """
150
- self._o.history_manager.reset()
151
- self.purged.emit()
152
- self.history_changed.emit()
153
-
154
- # Signal to notify all listeners that the level has been closed.
155
- closing = Signal[()]()
156
- closed = Signal[()]()
157
-
158
- @final
159
- def close(self, task_manager: AbstractCancelManager = VoidCancelManager()) -> None:
160
- """Close the level.
161
-
162
- If the level is not open, this does nothing.
163
-
164
- :param task_manager: The cancel manager through which cancel can be requested.
165
- :raises amulet.utils.task_manager.TaskCancelled: If the task is cancelled.
166
- """
167
- with self.lock_unique(task_manager=task_manager):
168
- if not self.is_open(task_manager=task_manager):
169
- # Do nothing if already closed
170
- return
171
- self.closing.emit()
172
- self._close()
173
- if self._open_data is not None:
174
- raise RuntimeError("_open_data is still set")
175
- self.closed.emit()
176
-
177
- @abstractmethod
178
- def _close(self) -> None:
179
- raise NotImplementedError
180
-
181
- @property
182
- @abstractmethod
183
- def platform(self) -> PlatformType:
184
- raise NotImplementedError
185
-
186
- @property
187
- @abstractmethod
188
- def max_game_version(self) -> VersionNumber:
189
- raise NotImplementedError
190
-
191
- # Emitted when the undo or redo count has changed
192
- history_changed = Signal[()]()
193
-
194
- @property
195
- def undo_count(self) -> int:
196
- return self._o.history_manager.undo_count
197
-
198
- def undo(self) -> None:
199
- with self.lock_unique(blocking=False):
200
- self._o.history_manager.undo()
201
-
202
- @property
203
- def redo_count(self) -> int:
204
- return self._o.history_manager.redo_count
205
-
206
- def redo(self) -> None:
207
- with self.lock_unique(blocking=False):
208
- self._o.history_manager.redo()
209
-
210
- @contextmanager
211
- def _lock(
212
- self,
213
- *,
214
- edit: bool,
215
- parallel: bool,
216
- blocking: bool,
217
- timeout: float,
218
- task_manager: AbstractCancelManager = VoidCancelManager(),
219
- ) -> Iterator[None]:
220
- if parallel:
221
- lock = self._level_lock.shared(blocking, timeout, task_manager)
222
- else:
223
- lock = self._level_lock.unique(blocking, timeout, task_manager)
224
- with lock:
225
- if edit and self.history_enabled:
226
- self._o.history_manager.create_undo_bin()
227
- yield
228
-
229
- def lock_unique(
230
- self,
231
- *,
232
- blocking: bool = True,
233
- timeout: float = -1,
234
- task_manager: AbstractCancelManager = VoidCancelManager(),
235
- ) -> ContextManager[None]:
236
- """
237
- Get exclusive access to the level without editing it.
238
- If you want to edit the level with exclusive access, use :meth:`edit_serial` instead.
239
- If the level is being used by other threads, this will block until they are done.
240
- Once acquired it will block other threads from accessing the level until this is released.
241
-
242
- >>> level: Level
243
- >>> with level.lock_unique():
244
- >>> # Lock is acquired before entering this block
245
- >>> ...
246
- >>> # Lock is released before exiting this block
247
-
248
- :param blocking: Should this block until the lock can be acquired. Default is True.
249
- :param timeout: Maximum amount of time to block for. Has no effect is blocking is False. Default is forever.
250
- :param task_manager: The cancel manager through which cancel can be requested.
251
- :return: A context manager to acquire the lock.
252
- :raises amulet.utils.shareable_lock.LockNotAcquired: If timeout was reached or cancel was called.
253
- """
254
- return self._lock(
255
- edit=False,
256
- parallel=False,
257
- blocking=blocking,
258
- timeout=timeout,
259
- task_manager=task_manager,
260
- )
261
-
262
- def lock_shared(
263
- self,
264
- *,
265
- blocking: bool = True,
266
- timeout: float = -1,
267
- task_manager: AbstractCancelManager = VoidCancelManager(),
268
- ) -> ContextManager[None]:
269
- """
270
- Share the level without editing it.
271
- If you want to edit the level in parallel with other threads, use :meth:`edit_parallel` instead.
272
-
273
- >>> level: Level
274
- >>> with level.lock_shared():
275
- >>> # Lock is acquired before entering this block
276
- >>> ...
277
- >>> # Lock is released before exiting this block
278
-
279
- :param blocking: Should this block until the lock can be acquired. Default is True.
280
- :param timeout: Maximum amount of time to block for. Has no effect is blocking is False. Default is forever.
281
- :param task_manager: The cancel manager through which cancel can be requested.
282
- :return: A context manager to acquire the lock.
283
- :raises amulet.utils.shareable_lock.LockNotAcquired: If timeout was reached or cancel was called.
284
- """
285
- return self._lock(
286
- edit=False,
287
- parallel=True,
288
- blocking=blocking,
289
- timeout=timeout,
290
- task_manager=task_manager,
291
- )
292
-
293
- def edit_serial(
294
- self,
295
- *,
296
- blocking: bool = True,
297
- timeout: float = -1,
298
- task_manager: AbstractCancelManager = VoidCancelManager(),
299
- ) -> ContextManager[None]:
300
- """
301
- Get exclusive editing permissions for this level.
302
- This is useful if you are doing something nuclear to the level and you don't want other code editing it at
303
- the same time. Usually :meth:`edit_parallel` is sufficient when used with other locks.
304
-
305
- >>> level: Level
306
- >>> with level.edit_serial(): # This will block the thread until all other threads have finished with the level
307
- >>> # Lock is acquired before entering this block
308
- >>> # any code here will be run without any other threads touching the level
309
- >>> ...
310
- >>> # Lock is released before exiting this block
311
- >>> # Other threads can modify the level here
312
-
313
- :param blocking: Should this block until the lock can be acquired. Default is True.
314
- :param timeout: Maximum amount of time to block for. Has no effect is blocking is False. Default is forever.
315
- :param task_manager: The cancel manager through which cancel can be requested.
316
- :return: A context manager to acquire the lock.
317
- :raises amulet.utils.shareable_lock.LockNotAcquired: If timeout was reached or cancel was called.
318
- """
319
- return self._lock(
320
- edit=True,
321
- parallel=False,
322
- blocking=blocking,
323
- timeout=timeout,
324
- task_manager=task_manager,
325
- )
326
-
327
- def edit_parallel(
328
- self,
329
- *,
330
- blocking: bool = True,
331
- timeout: float = -1,
332
- task_manager: AbstractCancelManager = VoidCancelManager(),
333
- ) -> ContextManager[None]:
334
- """
335
- Edit the level in parallal with other threads.
336
- This allows multiple threads that don't make nuclear changes to work in parallel.
337
- Before modifying the level data, you must use this or :meth:`edit_serial`.
338
- Using this ensures that no nuclear changes are made by other threads while your code is running.
339
- If another thread has exclusive access to the level, this will block until it has finished and vice versa.
340
- If you are going to make any nuclear changes to the level you must use :meth:`edit_serial` instead.
341
-
342
- >>> level: Level
343
- >>> with level.edit_serial(): # This will block the thread until all other unique calls have finished with the level
344
- >>> # Lock is acquired before entering this block
345
- >>> # any code here will be run in parallel with other parallel calls.
346
- >>> ...
347
- >>> # Lock is released before exiting this block
348
- >>> # Other threads can modify the level here
349
-
350
- :param blocking: Should this block until the lock can be acquired. Default is True.
351
- :param timeout: Maximum amount of time to block for. Has no effect is blocking is False. Default is forever.
352
- :param task_manager: The cancel manager through which cancel can be requested.
353
- :return: A context manager to acquire the lock.
354
- :raises amulet.utils.shareable_lock.LockNotAcquired: If timeout was reached or cancel was called.
355
- """
356
- return self._lock(
357
- edit=True,
358
- parallel=True,
359
- blocking=blocking,
360
- timeout=timeout,
361
- task_manager=task_manager,
362
- )
363
-
364
- history_enabled_changed = Signal[()]()
365
-
366
- @property
367
- def history_enabled(self) -> bool:
368
- """Should edit_serial and edit_parallel create undo points and should setting data load the original state."""
369
- return self._history_enabled
370
-
371
- @history_enabled.setter
372
- def history_enabled(self, history_enabled: bool) -> None:
373
- self._history_enabled = history_enabled
374
- self.history_enabled_changed.emit()
375
-
376
- @property
377
- def thumbnail(self) -> Image.Image:
378
- global missing_world_icon
379
- if missing_world_icon is None:
380
- missing_world_icon = Image.open(missing_world_icon_path)
381
- return missing_world_icon
382
-
383
- @property
384
- @abstractmethod
385
- def level_name(self) -> str:
386
- """The human-readable name of the level"""
387
- raise NotImplementedError
388
-
389
- @property
390
- @abstractmethod
391
- def modified_time(self) -> float:
392
- """The unix float timestamp of when the level was last modified."""
393
- raise NotImplementedError
394
-
395
- @property
396
- def sub_chunk_size(self) -> int:
397
- """
398
- The dimensions of a sub-chunk.
399
- """
400
- return 16
401
-
402
- @abstractmethod
403
- def dimension_ids(self) -> frozenset[DimensionId]:
404
- raise NotImplementedError
405
-
406
- @abstractmethod
407
- def get_dimension(self, dimension_id: DimensionId) -> DimensionT:
408
- raise NotImplementedError
409
-
410
- @property
411
- @abstractmethod
412
- def raw(self) -> RawLevelT:
413
- """
414
- Direct access to the level data.
415
- Only use this if you know what you are doing.
416
- """
417
- raise NotImplementedError
418
-
419
- @property
420
- @abstractmethod
421
- def player(self) -> PlayerStorage:
422
- """Methods to interact with the player data for the level."""
423
- raise NotImplementedError
424
-
425
- @property
426
- @abstractmethod
427
- def native_chunk_class(self) -> Type[Chunk]:
428
- raise NotImplementedError
429
-
430
-
431
- LevelT = TypeVar("LevelT", bound=Level)
432
-
433
-
434
- class LevelFriend(Generic[LevelT]):
435
- """A base class for friends of the level that need to store a pointer to the level"""
436
-
437
- _l_ref: Callable[[], LevelT | None]
438
-
439
- __slots__ = ("_level_ref",)
440
-
441
- def __init__(self, level_ref: Callable[[], LevelT | None]):
442
- self._l_ref = level_ref
443
-
444
- @property
445
- def _l(self) -> LevelT:
446
- level = self._l_ref()
447
- if level is None:
448
- raise RuntimeError("The level is no longer accessible")
449
- return level
@@ -1,42 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Any
4
- from abc import ABC, abstractmethod
5
-
6
- from ._level import Level
7
-
8
-
9
- class LoadableLevel(Level, ABC):
10
- """Level extension class for levels that can be loaded from existing data."""
11
-
12
- __slots__ = ()
13
-
14
- @staticmethod
15
- @abstractmethod
16
- def can_load(token: Any) -> bool:
17
- """
18
- Returns whether this level class is able to load the given data.
19
-
20
- :param token: The token to check. Usually a file or directory path.
21
- :return: True if the level can be loaded by this format wrapper, False otherwise.
22
- """
23
- raise NotImplementedError
24
-
25
- @classmethod
26
- @abstractmethod
27
- def load(cls, token: Any) -> LoadableLevel:
28
- """
29
- Create a new instance from existing data.
30
- You must call :meth:`~amulet.level.abc.Level.open` to open the level for editing.
31
- :param token: The token to use to load the data.
32
- :return: A new Level instance
33
- """
34
- raise NotImplementedError
35
-
36
- @abstractmethod
37
- def reload(self) -> None:
38
- """
39
- Reload the metadata in the existing instance.
40
- This can only be done when the level is not open.
41
- """
42
- raise NotImplementedError
@@ -1,7 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from ._level import LevelFriend
4
-
5
-
6
- class PlayerStorage(LevelFriend):
7
- __slots__ = ()
@@ -1,187 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Iterable, TypeVar, Generic, Callable
4
- from abc import ABC, abstractmethod
5
- from weakref import ref
6
-
7
- from amulet.data_types import ChunkCoordinates, DimensionId
8
- from amulet.chunk import Chunk
9
- from amulet.block import BlockStack
10
- from amulet.biome import Biome
11
- from amulet.selection import SelectionGroup
12
-
13
- PlayerIDT = TypeVar("PlayerIDT")
14
- RawPlayerT = TypeVar("RawPlayerT")
15
- ChunkT = TypeVar("ChunkT", bound=Chunk)
16
- RawChunkT = TypeVar("RawChunkT")
17
-
18
-
19
- class RawDimension(ABC, Generic[RawChunkT, ChunkT]):
20
- __slots__ = ()
21
-
22
- @property
23
- @abstractmethod
24
- def dimension_id(self) -> DimensionId:
25
- raise NotImplementedError
26
-
27
- @abstractmethod
28
- def bounds(self) -> SelectionGroup:
29
- """The editable region of the dimension."""
30
- raise NotImplementedError
31
-
32
- @abstractmethod
33
- def default_block(self) -> BlockStack:
34
- """The default block for this dimension"""
35
- raise NotImplementedError
36
-
37
- @abstractmethod
38
- def default_biome(self) -> Biome:
39
- """The default biome for this dimension"""
40
- raise NotImplementedError
41
-
42
- @abstractmethod
43
- def all_chunk_coords(self) -> Iterable[ChunkCoordinates]:
44
- """Get an iterable of all the chunk coordinates that exist in the raw level data."""
45
- raise NotImplementedError
46
-
47
- @abstractmethod
48
- def has_chunk(self, cx: int, cz: int) -> bool:
49
- """Check if the chunk exists in the raw level data."""
50
- raise NotImplementedError
51
-
52
- @abstractmethod
53
- def delete_chunk(self, cx: int, cz: int) -> None:
54
- raise NotImplementedError
55
-
56
- @abstractmethod
57
- def get_raw_chunk(self, cx: int, cz: int) -> RawChunkT:
58
- """Get the chunk data in its raw format.
59
-
60
- This is usually the exact data that exists on disk.
61
- The raw chunk format varies between each level class.
62
- Each call to this method will return a unique object.
63
-
64
- :param cx: The chunk x coordinate
65
- :param cz: The chunk z coordinate
66
- :return: The raw chunk.
67
- """
68
- raise NotImplementedError
69
-
70
- @abstractmethod
71
- def set_raw_chunk(self, cx: int, cz: int, chunk: RawChunkT) -> None:
72
- """Set the chunk in its raw format."""
73
- raise NotImplementedError
74
-
75
- @abstractmethod
76
- def raw_chunk_to_native_chunk(
77
- self, raw_chunk: RawChunkT, cx: int, cz: int
78
- ) -> ChunkT:
79
- """Unpack data from the raw chunk format (as stored on disk) into editable classes.
80
-
81
- This takes ownership of the raw_chunk object.
82
-
83
- :param cx: The chunk x coordinate
84
- :param cz: The chunk z coordinate
85
- :param raw_chunk: The raw chunk to unpack.
86
- :return: The unpacked chunk.
87
- """
88
- raise NotImplementedError
89
-
90
- @abstractmethod
91
- def native_chunk_to_raw_chunk(self, chunk: ChunkT, cx: int, cz: int) -> RawChunkT:
92
- """Pack the data from the editable classes into the raw format.
93
-
94
- This takes ownership of the chunk object.
95
-
96
- :param cx: The chunk x coordinate
97
- :param cz: The chunk z coordinate
98
- :param chunk: The native chunk to pack
99
- :return: The packed chunk.
100
- """
101
- raise NotImplementedError
102
-
103
-
104
- RawDimensionT = TypeVar("RawDimensionT", bound=RawDimension)
105
-
106
-
107
- class RawLevel(ABC, Generic[RawDimensionT]):
108
- """
109
- A class with raw access to the level.
110
- All of these methods directly read from or write to the level.
111
- There is no way to undo changes made with these methods.
112
- """
113
-
114
- __slots__ = ("__weakref__",)
115
-
116
- @abstractmethod
117
- def dimension_ids(self) -> frozenset[DimensionId]:
118
- raise NotImplementedError
119
-
120
- @abstractmethod
121
- def get_dimension(self, dimension_id: DimensionId) -> RawDimensionT:
122
- raise NotImplementedError
123
-
124
-
125
- RawLevelT = TypeVar("RawLevelT", bound=RawLevel)
126
-
127
-
128
- class RawLevelFriend(Generic[RawLevelT]):
129
- """A base class for friends of the raw level that need to store a pointer to the raw level"""
130
-
131
- _r_ref: Callable[[], RawLevelT | None]
132
-
133
- __slots__ = ("_r_ref",)
134
-
135
- def __init__(self, raw_level_ref: Callable[[], RawLevelT | None]) -> None:
136
- self._r_ref = raw_level_ref
137
-
138
- @property
139
- def _r(self) -> RawLevelT:
140
- r = self._r_ref()
141
- if r is None:
142
- raise RuntimeError("Cannot access raw level")
143
- return r
144
-
145
-
146
- class RawLevelPlayerComponent(ABC, Generic[PlayerIDT, RawPlayerT]):
147
- """An extension for the RawLevel class for implementations that have player data."""
148
-
149
- __slots__ = ()
150
-
151
- @abstractmethod
152
- def players(self) -> Iterable[PlayerIDT]:
153
- raise NotImplementedError
154
-
155
- @abstractmethod
156
- def has_player(self, player_id: PlayerIDT) -> bool:
157
- raise NotImplementedError
158
-
159
- @abstractmethod
160
- def get_raw_player(self, player_id: PlayerIDT) -> RawPlayerT:
161
- raise NotImplementedError
162
-
163
- @abstractmethod
164
- def set_raw_player(self, player_id: PlayerIDT, player: RawPlayerT) -> None:
165
- raise NotImplementedError
166
-
167
-
168
- class RawLevelBufferedComponent(ABC):
169
- """
170
- An extension for the RawLevel class for implementations that need a data buffer.
171
-
172
- This should be used for formats that cannot stream data and must read and write the data in one go.
173
- """
174
-
175
- __slots__ = ()
176
-
177
- @abstractmethod
178
- def pre_save(self) -> None:
179
- """A method to run before data is pushed to the raw level.
180
- This is useful to save the level.dat before pushing chunk data."""
181
- raise NotImplementedError
182
-
183
- @abstractmethod
184
- def save(self) -> None:
185
- """A method to run after data is pushed to the raw level.
186
- This is useful for structure files to write the actual data to disk."""
187
- raise NotImplementedError