amulet-core 2.0a7__cp312-cp312-win_amd64.whl → 2.0.1.0.1297307203.19.43.34808.0a0__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.
- amulet/core/__init__.py +36 -0
- amulet/core/__pyinstaller/hook-amulet.core.py +4 -0
- amulet/core/_amulet_core.cp312-win_amd64.pyd +0 -0
- amulet/core/_amulet_core.pyi +7 -0
- amulet/{_version.py → core/_version.py} +3 -3
- amulet/core/amulet_core.dll +0 -0
- amulet/core/amulet_core.lib +0 -0
- amulet/core/amulet_coreConfig.cmake +18 -0
- amulet/{biome.pyi → core/biome/__init__.pyi} +3 -3
- amulet/core/biome/biome.hpp +53 -0
- amulet/{block.pyi → core/block/__init__.pyi} +25 -26
- amulet/core/block/block.hpp +156 -0
- amulet/{block_entity.pyi → core/block_entity/__init__.pyi} +7 -7
- amulet/core/block_entity/block_entity.hpp +84 -0
- amulet/{errors.py → core/chunk/__init__.pyi} +37 -33
- amulet/core/chunk/chunk.hpp +126 -0
- amulet/core/chunk/component/__init__.pyi +18 -0
- amulet/core/chunk/component/biome_3d_component.hpp +96 -0
- amulet/core/chunk/component/block_component.hpp +101 -0
- amulet/core/chunk/component/block_component.pyi +28 -0
- amulet/core/chunk/component/block_entity_component.hpp +119 -0
- amulet/core/chunk/component/section_array_map.hpp +129 -0
- amulet/{chunk_components.pyi → core/chunk/component/section_array_map.pyi} +4 -24
- amulet/core/dll.hpp +21 -0
- amulet/core/entity/__init__.pyi +105 -0
- amulet/core/entity/entity.hpp +100 -0
- amulet/{palette → core/palette}/__init__.pyi +2 -2
- amulet/core/palette/biome_palette.hpp +65 -0
- amulet/{palette → core/palette}/biome_palette.pyi +8 -8
- amulet/core/palette/block_palette.hpp +71 -0
- amulet/{palette → core/palette}/block_palette.pyi +12 -10
- amulet/core/selection/__init__.pyi +8 -0
- amulet/core/selection/box.hpp +86 -0
- amulet/core/selection/box.pyi +215 -0
- amulet/core/selection/group.hpp +80 -0
- amulet/core/selection/group.pyi +213 -0
- amulet/{version.pyi → core/version/__init__.pyi} +58 -10
- amulet/core/version/version.hpp +204 -0
- {amulet_core-2.0a7.dist-info → amulet_core-2.0.1.0.1297307203.19.43.34808.0a0.dist-info}/METADATA +25 -20
- amulet_core-2.0.1.0.1297307203.19.43.34808.0a0.dist-info/RECORD +45 -0
- {amulet_core-2.0a7.dist-info → amulet_core-2.0.1.0.1297307203.19.43.34808.0a0.dist-info}/WHEEL +1 -1
- amulet_core-2.0.1.0.1297307203.19.43.34808.0a0.dist-info/entry_points.txt +2 -0
- amulet/__init__.cp312-win_amd64.pyd +0 -0
- amulet/__init__.py.cpp +0 -43
- amulet/__init__.pyi +0 -28
- amulet/__pyinstaller/hook-amulet.py +0 -4
- amulet/_init.py +0 -26
- amulet/biome.cpp +0 -36
- amulet/biome.hpp +0 -43
- amulet/biome.py.cpp +0 -122
- amulet/block.cpp +0 -435
- amulet/block.hpp +0 -119
- amulet/block.py.cpp +0 -377
- amulet/block_entity.cpp +0 -12
- amulet/block_entity.hpp +0 -56
- amulet/block_entity.py.cpp +0 -115
- amulet/chunk.cpp +0 -16
- amulet/chunk.hpp +0 -99
- amulet/chunk.py.cpp +0 -80
- amulet/chunk.pyi +0 -28
- amulet/chunk_components/biome_3d_component.cpp +0 -5
- amulet/chunk_components/biome_3d_component.hpp +0 -79
- amulet/chunk_components/block_component.cpp +0 -41
- amulet/chunk_components/block_component.hpp +0 -88
- amulet/chunk_components/block_entity_component.cpp +0 -5
- amulet/chunk_components/block_entity_component.hpp +0 -147
- amulet/chunk_components/section_array_map.cpp +0 -129
- amulet/chunk_components/section_array_map.hpp +0 -147
- amulet/collections/eq.py.hpp +0 -37
- amulet/collections/hash.py.hpp +0 -27
- amulet/collections/holder.py.hpp +0 -37
- amulet/collections/iterator.py.hpp +0 -80
- amulet/collections/mapping.py.hpp +0 -199
- amulet/collections/mutable_mapping.py.hpp +0 -226
- amulet/collections/sequence.py.hpp +0 -163
- amulet/collections.pyi +0 -40
- amulet/data_types.py +0 -29
- amulet/entity.py +0 -182
- amulet/game/__init__.py +0 -7
- amulet/game/_game.py +0 -152
- amulet/game/_universal/__init__.py +0 -1
- amulet/game/_universal/_biome.py +0 -17
- amulet/game/_universal/_block.py +0 -47
- amulet/game/_universal/_version.py +0 -68
- amulet/game/abc/__init__.py +0 -22
- amulet/game/abc/_block_specification.py +0 -150
- amulet/game/abc/biome.py +0 -213
- amulet/game/abc/block.py +0 -331
- amulet/game/abc/game_version_container.py +0 -25
- amulet/game/abc/json_interface.py +0 -27
- amulet/game/abc/version.py +0 -44
- amulet/game/bedrock/__init__.py +0 -1
- amulet/game/bedrock/_biome.py +0 -35
- amulet/game/bedrock/_block.py +0 -42
- amulet/game/bedrock/_version.py +0 -165
- amulet/game/java/__init__.py +0 -2
- amulet/game/java/_biome.py +0 -35
- amulet/game/java/_block.py +0 -60
- amulet/game/java/_version.py +0 -176
- amulet/game/translate/__init__.py +0 -12
- amulet/game/translate/_functions/__init__.py +0 -15
- amulet/game/translate/_functions/_code_functions/__init__.py +0 -0
- amulet/game/translate/_functions/_code_functions/_text.py +0 -553
- amulet/game/translate/_functions/_code_functions/banner_pattern.py +0 -67
- amulet/game/translate/_functions/_code_functions/bedrock_chest_connection.py +0 -152
- amulet/game/translate/_functions/_code_functions/bedrock_moving_block_pos.py +0 -88
- amulet/game/translate/_functions/_code_functions/bedrock_sign.py +0 -152
- amulet/game/translate/_functions/_code_functions/bedrock_skull_rotation.py +0 -16
- amulet/game/translate/_functions/_code_functions/custom_name.py +0 -146
- amulet/game/translate/_functions/_frozen.py +0 -66
- amulet/game/translate/_functions/_state.py +0 -54
- amulet/game/translate/_functions/_typing.py +0 -98
- amulet/game/translate/_functions/abc.py +0 -123
- amulet/game/translate/_functions/carry_nbt.py +0 -160
- amulet/game/translate/_functions/carry_properties.py +0 -80
- amulet/game/translate/_functions/code.py +0 -143
- amulet/game/translate/_functions/map_block_name.py +0 -66
- amulet/game/translate/_functions/map_nbt.py +0 -111
- amulet/game/translate/_functions/map_properties.py +0 -93
- amulet/game/translate/_functions/multiblock.py +0 -112
- amulet/game/translate/_functions/new_block.py +0 -42
- amulet/game/translate/_functions/new_entity.py +0 -43
- amulet/game/translate/_functions/new_nbt.py +0 -206
- amulet/game/translate/_functions/new_properties.py +0 -64
- amulet/game/translate/_functions/sequence.py +0 -51
- amulet/game/translate/_functions/walk_input_nbt.py +0 -331
- amulet/game/translate/_translator.py +0 -433
- amulet/img/__init__.py +0 -10
- amulet/img/missing_no.png +0 -0
- amulet/img/missing_pack.png +0 -0
- amulet/img/missing_world.png +0 -0
- amulet/io/binary_reader.hpp +0 -45
- amulet/io/binary_writer.hpp +0 -30
- amulet/item.py +0 -75
- amulet/level/__init__.pyi +0 -23
- amulet/level/_load.py +0 -100
- amulet/level/abc/__init__.py +0 -12
- amulet/level/abc/_chunk_handle.py +0 -335
- amulet/level/abc/_dimension.py +0 -86
- amulet/level/abc/_history/__init__.py +0 -1
- amulet/level/abc/_history/_cache.py +0 -224
- amulet/level/abc/_history/_history_manager.py +0 -291
- amulet/level/abc/_level/__init__.py +0 -5
- amulet/level/abc/_level/_compactable_level.py +0 -10
- amulet/level/abc/_level/_creatable_level.py +0 -28
- amulet/level/abc/_level/_disk_level.py +0 -17
- amulet/level/abc/_level/_level.py +0 -449
- amulet/level/abc/_level/_loadable_level.py +0 -42
- amulet/level/abc/_player_storage.py +0 -7
- amulet/level/abc/_raw_level.py +0 -187
- amulet/level/abc/_registry.py +0 -40
- amulet/level/java/__init__.pyi +0 -16
- amulet/level/java/_chunk_handle.py +0 -17
- amulet/level/java/_dimension.py +0 -20
- amulet/level/java/_level.py +0 -184
- amulet/level/java/_raw/__init__.pyi +0 -15
- amulet/level/java/_raw/_chunk.pyi +0 -23
- amulet/level/java/_raw/_constant.py +0 -9
- amulet/level/java/_raw/_data_pack/__init__.py +0 -2
- amulet/level/java/_raw/_data_pack/data_pack.py +0 -241
- amulet/level/java/_raw/_data_pack/data_pack_manager.py +0 -77
- amulet/level/java/_raw/_dimension.py +0 -86
- amulet/level/java/_raw/_level.py +0 -507
- amulet/level/java/_raw/_typing.py +0 -3
- amulet/level/java/_raw/java_chunk_decode.cpp +0 -531
- amulet/level/java/_raw/java_chunk_decode.hpp +0 -23
- amulet/level/java/_raw/java_chunk_encode.cpp +0 -25
- amulet/level/java/_raw/java_chunk_encode.hpp +0 -23
- amulet/level/java/anvil/__init__.py +0 -2
- amulet/level/java/anvil/_dimension.py +0 -170
- amulet/level/java/anvil/_region.py +0 -421
- amulet/level/java/anvil/_sector_manager.py +0 -223
- amulet/level/java/chunk.pyi +0 -81
- amulet/level/java/chunk_/_chunk.py +0 -260
- amulet/level/java/chunk_/components/inhabited_time.py +0 -12
- amulet/level/java/chunk_/components/last_update.py +0 -12
- amulet/level/java/chunk_/components/legacy_version.py +0 -12
- amulet/level/java/chunk_/components/light_populated.py +0 -12
- amulet/level/java/chunk_/components/named_height_2d.py +0 -37
- amulet/level/java/chunk_/components/status.py +0 -11
- amulet/level/java/chunk_/components/terrain_populated.py +0 -12
- amulet/level/java/chunk_components/data_version_component.cpp +0 -32
- amulet/level/java/chunk_components/data_version_component.hpp +0 -31
- amulet/level/java/chunk_components/java_raw_chunk_component.cpp +0 -56
- amulet/level/java/chunk_components/java_raw_chunk_component.hpp +0 -45
- amulet/level/java/chunk_components.pyi +0 -22
- amulet/level/java/java_chunk.cpp +0 -170
- amulet/level/java/java_chunk.hpp +0 -141
- amulet/level/java/long_array.hpp +0 -175
- amulet/level/java/long_array.pyi +0 -39
- amulet/level/temporary_level/__init__.py +0 -1
- amulet/level/temporary_level/_level.py +0 -16
- amulet/mesh/__init__.py +0 -0
- amulet/mesh/block/__init__.py +0 -1
- amulet/mesh/block/block_mesh.py +0 -369
- amulet/mesh/block/cube.py +0 -149
- amulet/mesh/block/missing_block.py +0 -20
- amulet/mesh/util.py +0 -17
- amulet/palette/biome_palette.hpp +0 -85
- amulet/palette/block_palette.cpp +0 -32
- amulet/palette/block_palette.hpp +0 -93
- amulet/player.py +0 -62
- amulet/pybind11/collections.hpp +0 -118
- amulet/pybind11/numpy.hpp +0 -26
- amulet/pybind11/py_module.hpp +0 -34
- amulet/pybind11/type_hints.hpp +0 -51
- amulet/pybind11/types.hpp +0 -25
- amulet/pybind11/typing.hpp +0 -7
- amulet/resource_pack/__init__.py +0 -62
- amulet/resource_pack/abc/__init__.py +0 -2
- amulet/resource_pack/abc/resource_pack.py +0 -38
- amulet/resource_pack/abc/resource_pack_manager.py +0 -87
- amulet/resource_pack/bedrock/__init__.py +0 -2
- amulet/resource_pack/bedrock/bedrock_vanilla_fix/pack_icon.png +0 -0
- amulet/resource_pack/bedrock/bedrock_vanilla_fix/textures/blocks/grass_carried.png +0 -0
- amulet/resource_pack/bedrock/bedrock_vanilla_fix/textures/blocks/grass_side_carried.png +0 -0
- amulet/resource_pack/bedrock/bedrock_vanilla_fix/textures/blocks/water.png +0 -0
- amulet/resource_pack/bedrock/blockshapes/__init__.py +0 -31
- amulet/resource_pack/bedrock/blockshapes/air.py +0 -35
- amulet/resource_pack/bedrock/blockshapes/base_blockshape.py +0 -29
- amulet/resource_pack/bedrock/blockshapes/bubble_column.py +0 -29
- amulet/resource_pack/bedrock/blockshapes/cake.py +0 -46
- amulet/resource_pack/bedrock/blockshapes/chest.py +0 -54
- amulet/resource_pack/bedrock/blockshapes/comparator.py +0 -51
- amulet/resource_pack/bedrock/blockshapes/cross_texture.py +0 -186
- amulet/resource_pack/bedrock/blockshapes/cross_texture0.py +0 -17
- amulet/resource_pack/bedrock/blockshapes/cross_texture_green.py +0 -16
- amulet/resource_pack/bedrock/blockshapes/cube.py +0 -38
- amulet/resource_pack/bedrock/blockshapes/default.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/door.py +0 -38
- amulet/resource_pack/bedrock/blockshapes/door1.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/door2.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/door3.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/door4.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/door5.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/door6.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/double_plant.py +0 -40
- amulet/resource_pack/bedrock/blockshapes/enchanting_table.py +0 -22
- amulet/resource_pack/bedrock/blockshapes/farmland.py +0 -22
- amulet/resource_pack/bedrock/blockshapes/fence.py +0 -22
- amulet/resource_pack/bedrock/blockshapes/flat.py +0 -55
- amulet/resource_pack/bedrock/blockshapes/flat_wall.py +0 -55
- amulet/resource_pack/bedrock/blockshapes/furnace.py +0 -44
- amulet/resource_pack/bedrock/blockshapes/furnace_lit.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/green_cube.py +0 -39
- amulet/resource_pack/bedrock/blockshapes/ladder.py +0 -36
- amulet/resource_pack/bedrock/blockshapes/lilypad.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/partial_block.py +0 -57
- amulet/resource_pack/bedrock/blockshapes/piston.py +0 -44
- amulet/resource_pack/bedrock/blockshapes/piston_arm.py +0 -72
- amulet/resource_pack/bedrock/blockshapes/portal_frame.py +0 -22
- amulet/resource_pack/bedrock/blockshapes/pressure_plate.py +0 -29
- amulet/resource_pack/bedrock/blockshapes/pumpkin.py +0 -36
- amulet/resource_pack/bedrock/blockshapes/pumpkin_carved.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/pumpkin_lit.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/red_dust.py +0 -14
- amulet/resource_pack/bedrock/blockshapes/repeater.py +0 -53
- amulet/resource_pack/bedrock/blockshapes/slab.py +0 -33
- amulet/resource_pack/bedrock/blockshapes/slab_double.py +0 -15
- amulet/resource_pack/bedrock/blockshapes/tree.py +0 -41
- amulet/resource_pack/bedrock/blockshapes/turtle_egg.py +0 -15
- amulet/resource_pack/bedrock/blockshapes/vine.py +0 -52
- amulet/resource_pack/bedrock/blockshapes/wall.py +0 -22
- amulet/resource_pack/bedrock/blockshapes/water.py +0 -38
- amulet/resource_pack/bedrock/download_resources.py +0 -147
- amulet/resource_pack/bedrock/resource_pack.py +0 -40
- amulet/resource_pack/bedrock/resource_pack_manager.py +0 -361
- amulet/resource_pack/bedrock/sort_blockshapes.py +0 -15
- amulet/resource_pack/java/__init__.py +0 -2
- amulet/resource_pack/java/download_resources.py +0 -212
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_black.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_blue.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_brown.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_cyan.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_gray.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_green.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_light_blue.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_light_gray.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_lime.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_magenta.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_orange.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_pink.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_purple.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_red.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_white.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_yellow.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/barrier.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/end_portal.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/grass.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/lava.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/structure_void.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water.png +0 -0
- amulet/resource_pack/java/java_vanilla_fix/pack.png +0 -0
- amulet/resource_pack/java/resource_pack.py +0 -44
- amulet/resource_pack/java/resource_pack_manager.py +0 -551
- amulet/resource_pack/unknown_resource_pack.py +0 -10
- amulet/selection/__init__.py +0 -2
- amulet/selection/abstract_selection.py +0 -342
- amulet/selection/box.py +0 -852
- amulet/selection/group.py +0 -481
- amulet/utils/__init__.pyi +0 -23
- amulet/utils/call_spec/__init__.py +0 -24
- amulet/utils/call_spec/_call_spec.py +0 -257
- amulet/utils/comment_json.py +0 -188
- amulet/utils/format_utils.py +0 -41
- amulet/utils/generator.py +0 -18
- amulet/utils/matrix.py +0 -243
- amulet/utils/numpy.hpp +0 -36
- amulet/utils/numpy.pyi +0 -11
- amulet/utils/numpy_helpers.py +0 -19
- amulet/utils/shareable_lock.py +0 -335
- amulet/utils/signal/__init__.py +0 -10
- amulet/utils/signal/_signal.py +0 -228
- amulet/utils/task_manager.py +0 -235
- amulet/utils/typed_property.py +0 -111
- amulet/utils/weakref.py +0 -70
- amulet/utils/world_utils.py +0 -102
- amulet/version.cpp +0 -136
- amulet/version.hpp +0 -142
- amulet/version.py.cpp +0 -281
- amulet_core-2.0a7.dist-info/RECORD +0 -295
- amulet_core-2.0a7.dist-info/entry_points.txt +0 -2
- /amulet/{__pyinstaller → core/__pyinstaller}/__init__.py +0 -0
- /amulet/{py.typed → core/py.typed} +0 -0
- {amulet_core-2.0a7.dist-info → amulet_core-2.0.1.0.1297307203.19.43.34808.0a0.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
|
amulet/level/abc/_raw_level.py
DELETED
|
@@ -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
|