amulet-core 2.0a8__cp311-cp311-win_amd64.whl → 2.0.1.0.1297307203.19.43.34808.0a1__cp311-cp311-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.cp311-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.0a8.dist-info → amulet_core-2.0.1.0.1297307203.19.43.34808.0a1.dist-info}/METADATA +25 -20
- amulet_core-2.0.1.0.1297307203.19.43.34808.0a1.dist-info/RECORD +45 -0
- {amulet_core-2.0a8.dist-info → amulet_core-2.0.1.0.1297307203.19.43.34808.0a1.dist-info}/WHEEL +1 -1
- amulet_core-2.0.1.0.1297307203.19.43.34808.0a1.dist-info/entry_points.txt +2 -0
- amulet/__init__.cp311-win_amd64.pyd +0 -0
- amulet/__init__.py.cpp +0 -45
- amulet/__init__.pyi +0 -30
- 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 -100
- 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 -358
- 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__.pyi +0 -301
- amulet/mesh/block/_cube.py +0 -198
- amulet/mesh/block/_missing_block.py +0 -20
- amulet/mesh/block/block_mesh.cpp +0 -107
- amulet/mesh/block/block_mesh.hpp +0 -207
- 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 -63
- 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 -85
- 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 -563
- 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/cast.py +0 -10
- 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.0a8.dist-info/RECORD +0 -241
- amulet_core-2.0a8.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.0a8.dist-info → amulet_core-2.0.1.0.1297307203.19.43.34808.0a1.dist-info}/top_level.txt +0 -0
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
from typing import Iterable, TYPE_CHECKING, Callable
|
|
3
|
-
|
|
4
|
-
from amulet.biome import Biome
|
|
5
|
-
from amulet.block import BlockStack
|
|
6
|
-
from amulet.data_types import DimensionId, ChunkCoordinates
|
|
7
|
-
from amulet.level.abc import RawDimension, RawLevelFriend
|
|
8
|
-
from amulet.selection import SelectionGroup
|
|
9
|
-
|
|
10
|
-
from amulet.level.java.anvil import RawChunkType, AnvilDimension
|
|
11
|
-
from amulet.level.java.chunk import JavaChunk
|
|
12
|
-
from ._typing import InternalDimensionId
|
|
13
|
-
|
|
14
|
-
from ._chunk import decode_chunk, encode_chunk
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if TYPE_CHECKING:
|
|
18
|
-
from ._level import JavaRawLevel
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class JavaRawDimension(
|
|
22
|
-
RawLevelFriend["JavaRawLevel"], RawDimension[RawChunkType, JavaChunk]
|
|
23
|
-
):
|
|
24
|
-
def __init__(
|
|
25
|
-
self,
|
|
26
|
-
raw_level_ref: Callable[[], JavaRawLevel | None],
|
|
27
|
-
anvil_dimension: AnvilDimension,
|
|
28
|
-
relative_path: InternalDimensionId,
|
|
29
|
-
dimension_id: DimensionId,
|
|
30
|
-
bounds: SelectionGroup,
|
|
31
|
-
default_block: BlockStack,
|
|
32
|
-
default_biome: Biome,
|
|
33
|
-
) -> None:
|
|
34
|
-
super().__init__(raw_level_ref)
|
|
35
|
-
self._anvil_dimension = anvil_dimension
|
|
36
|
-
self._relative_path = relative_path
|
|
37
|
-
self._dimension_id = dimension_id
|
|
38
|
-
self._bounds = bounds
|
|
39
|
-
self._default_block = default_block
|
|
40
|
-
self._default_biome = default_biome
|
|
41
|
-
|
|
42
|
-
@property
|
|
43
|
-
def dimension_id(self) -> DimensionId:
|
|
44
|
-
return self._dimension_id
|
|
45
|
-
|
|
46
|
-
@property
|
|
47
|
-
def relative_path(self) -> InternalDimensionId:
|
|
48
|
-
return self._relative_path
|
|
49
|
-
|
|
50
|
-
def bounds(self) -> SelectionGroup:
|
|
51
|
-
return self._bounds
|
|
52
|
-
|
|
53
|
-
def default_block(self) -> BlockStack:
|
|
54
|
-
return self._default_block
|
|
55
|
-
|
|
56
|
-
def default_biome(self) -> Biome:
|
|
57
|
-
return self._default_biome
|
|
58
|
-
|
|
59
|
-
def all_chunk_coords(self) -> Iterable[ChunkCoordinates]:
|
|
60
|
-
yield from self._anvil_dimension.all_chunk_coords()
|
|
61
|
-
|
|
62
|
-
def has_chunk(self, cx: int, cz: int) -> bool:
|
|
63
|
-
return self._anvil_dimension.has_chunk(cx, cz)
|
|
64
|
-
|
|
65
|
-
def delete_chunk(self, cx: int, cz: int) -> None:
|
|
66
|
-
self._anvil_dimension.delete_chunk(cx, cz)
|
|
67
|
-
|
|
68
|
-
def get_raw_chunk(self, cx: int, cz: int) -> RawChunkType:
|
|
69
|
-
return self._anvil_dimension.get_chunk_data(cx, cz)
|
|
70
|
-
|
|
71
|
-
def set_raw_chunk(self, cx: int, cz: int, chunk: RawChunkType) -> None:
|
|
72
|
-
self._anvil_dimension.put_chunk_data(cx, cz, chunk)
|
|
73
|
-
|
|
74
|
-
def raw_chunk_to_native_chunk(
|
|
75
|
-
self, raw_chunk: RawChunkType, cx: int, cz: int
|
|
76
|
-
) -> JavaChunk:
|
|
77
|
-
return decode_chunk(self._r, self, raw_chunk, cx, cz)
|
|
78
|
-
|
|
79
|
-
def native_chunk_to_raw_chunk(
|
|
80
|
-
self, chunk: JavaChunk, cx: int, cz: int
|
|
81
|
-
) -> RawChunkType:
|
|
82
|
-
return encode_chunk(self._r, self, chunk, cx, cz)
|
|
83
|
-
|
|
84
|
-
def compact(self) -> None:
|
|
85
|
-
"""Compact all region files"""
|
|
86
|
-
self._anvil_dimension.compact()
|
amulet/level/java/_raw/_level.py
DELETED
|
@@ -1,507 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import BinaryIO, Callable
|
|
4
|
-
import copy
|
|
5
|
-
from threading import RLock
|
|
6
|
-
import logging
|
|
7
|
-
from dataclasses import dataclass
|
|
8
|
-
import shutil
|
|
9
|
-
import time
|
|
10
|
-
import glob
|
|
11
|
-
import json
|
|
12
|
-
import struct
|
|
13
|
-
import os
|
|
14
|
-
|
|
15
|
-
import portalocker
|
|
16
|
-
|
|
17
|
-
from amulet_nbt import (
|
|
18
|
-
IntTag,
|
|
19
|
-
LongTag,
|
|
20
|
-
StringTag,
|
|
21
|
-
ListTag,
|
|
22
|
-
CompoundTag,
|
|
23
|
-
read_nbt,
|
|
24
|
-
NamedTag,
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
from amulet.data_types import DimensionId
|
|
28
|
-
from amulet.block import BlockStack, Block
|
|
29
|
-
from amulet.biome import Biome
|
|
30
|
-
from amulet.game import get_game_version
|
|
31
|
-
from amulet.selection import SelectionGroup, SelectionBox
|
|
32
|
-
from amulet.errors import LevelWriteError
|
|
33
|
-
from amulet.level.abc import (
|
|
34
|
-
RawLevel,
|
|
35
|
-
IdRegistry,
|
|
36
|
-
)
|
|
37
|
-
from amulet.version import VersionNumber
|
|
38
|
-
from amulet.utils.signal import Signal, SignalInstanceCacheName
|
|
39
|
-
from amulet.utils.weakref import DetachableWeakRef
|
|
40
|
-
|
|
41
|
-
from amulet.level.java.anvil import AnvilDimension
|
|
42
|
-
from ._data_pack import DataPackManager, DataPack
|
|
43
|
-
from ._dimension import JavaRawDimension
|
|
44
|
-
from ._typing import InternalDimensionId
|
|
45
|
-
from ._constant import OVERWORLD, THE_NETHER, THE_END, DefaultSelection
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
log = logging.getLogger(__name__)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
@dataclass
|
|
52
|
-
class JavaCreateArgsV1:
|
|
53
|
-
"""A class to house call arguments to create.
|
|
54
|
-
|
|
55
|
-
If the call arguments to create need to be modified in the future a new arguments class can be created.
|
|
56
|
-
The create method can inspect which class it was given and access arguments accordingly.
|
|
57
|
-
"""
|
|
58
|
-
|
|
59
|
-
overwrite: bool
|
|
60
|
-
path: str
|
|
61
|
-
version: VersionNumber
|
|
62
|
-
level_name: str
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
class JavaRawLevelOpenData:
|
|
66
|
-
back_reference: Callable[[], JavaRawLevel | None]
|
|
67
|
-
detach_back_reference: Callable[[], None]
|
|
68
|
-
lock_file: BinaryIO
|
|
69
|
-
lock_time: float
|
|
70
|
-
data_pack: DataPackManager
|
|
71
|
-
dimensions: dict[InternalDimensionId, JavaRawDimension]
|
|
72
|
-
dimension_ids: dict[DimensionId, InternalDimensionId]
|
|
73
|
-
dimensions_lock: RLock
|
|
74
|
-
block_id_override: IdRegistry
|
|
75
|
-
biome_id_override: IdRegistry
|
|
76
|
-
|
|
77
|
-
def __init__(
|
|
78
|
-
self,
|
|
79
|
-
raw_level: JavaRawLevel,
|
|
80
|
-
lock_file: BinaryIO,
|
|
81
|
-
lock_time: float,
|
|
82
|
-
data_pack: DataPackManager,
|
|
83
|
-
) -> None:
|
|
84
|
-
self.back_reference, self.detach_back_reference = DetachableWeakRef.new(
|
|
85
|
-
raw_level
|
|
86
|
-
)
|
|
87
|
-
self.lock_file = lock_file
|
|
88
|
-
self.lock_time = lock_time
|
|
89
|
-
self.data_pack = data_pack
|
|
90
|
-
self.dimensions = {}
|
|
91
|
-
self.dimension_ids = {}
|
|
92
|
-
self.dimensions_lock = RLock()
|
|
93
|
-
self.block_id_override = IdRegistry()
|
|
94
|
-
self.biome_id_override = IdRegistry()
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
class JavaRawLevel(RawLevel[JavaRawDimension]):
|
|
98
|
-
_path: str
|
|
99
|
-
_level_dat: NamedTag
|
|
100
|
-
_data_version: VersionNumber
|
|
101
|
-
_raw_open_data: JavaRawLevelOpenData | None
|
|
102
|
-
|
|
103
|
-
__slots__ = (
|
|
104
|
-
"_path",
|
|
105
|
-
"_level_dat",
|
|
106
|
-
"_data_version",
|
|
107
|
-
"_raw_open_data",
|
|
108
|
-
SignalInstanceCacheName,
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
def __init__(self, _ikwiad: bool = False) -> None:
|
|
112
|
-
if not _ikwiad:
|
|
113
|
-
raise RuntimeError(
|
|
114
|
-
"JavaRawLevel must be constructed using the create or load classmethod."
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
@classmethod
|
|
118
|
-
def load(cls, path: str) -> JavaRawLevel:
|
|
119
|
-
self = cls(True)
|
|
120
|
-
self._path = path
|
|
121
|
-
self._raw_open_data = None
|
|
122
|
-
self.reload()
|
|
123
|
-
return self
|
|
124
|
-
|
|
125
|
-
@classmethod
|
|
126
|
-
def create(cls, args: JavaCreateArgsV1) -> JavaRawLevel:
|
|
127
|
-
overwrite = args.overwrite
|
|
128
|
-
path = args.path
|
|
129
|
-
version = args.version
|
|
130
|
-
level_name = args.level_name
|
|
131
|
-
|
|
132
|
-
if os.path.isdir(path):
|
|
133
|
-
if overwrite:
|
|
134
|
-
shutil.rmtree(path)
|
|
135
|
-
else:
|
|
136
|
-
raise LevelWriteError(f"A world already exists at the path {path}")
|
|
137
|
-
os.makedirs(path, exist_ok=True)
|
|
138
|
-
|
|
139
|
-
data_version = get_game_version("java", version).max_version
|
|
140
|
-
|
|
141
|
-
root = CompoundTag()
|
|
142
|
-
root["Data"] = data = CompoundTag()
|
|
143
|
-
data["version"] = IntTag(19133)
|
|
144
|
-
data["DataVersion"] = IntTag(data_version[0])
|
|
145
|
-
data["LastPlayed"] = LongTag(int(time.time() * 1000))
|
|
146
|
-
data["LevelName"] = StringTag(level_name)
|
|
147
|
-
|
|
148
|
-
root.save_to(os.path.join(path, "level.dat"))
|
|
149
|
-
|
|
150
|
-
return cls.load(path)
|
|
151
|
-
|
|
152
|
-
def is_open(self) -> bool:
|
|
153
|
-
return self._raw_open_data is not None
|
|
154
|
-
|
|
155
|
-
@property
|
|
156
|
-
def _o(self) -> JavaRawLevelOpenData:
|
|
157
|
-
o = self._raw_open_data
|
|
158
|
-
if o is None:
|
|
159
|
-
raise RuntimeError("The level is not open.")
|
|
160
|
-
return o
|
|
161
|
-
|
|
162
|
-
def _update_data_version(self) -> None:
|
|
163
|
-
"""Pull the data version from the level.dat file"""
|
|
164
|
-
self._data_version = VersionNumber(
|
|
165
|
-
self._level_dat.compound.get_compound("Data", CompoundTag())
|
|
166
|
-
.get_int("DataVersion", IntTag(-1))
|
|
167
|
-
.py_int
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
def reload(self) -> None:
|
|
171
|
-
"""Reload the raw level."""
|
|
172
|
-
if self.is_open():
|
|
173
|
-
raise RuntimeError("Cannot reload a level when it is open.")
|
|
174
|
-
self._level_dat = read_nbt(os.path.join(self.path, "level.dat"))
|
|
175
|
-
self._update_data_version()
|
|
176
|
-
|
|
177
|
-
opened = Signal[()]()
|
|
178
|
-
|
|
179
|
-
def open(self) -> None:
|
|
180
|
-
"""Open the raw level."""
|
|
181
|
-
if self.is_open():
|
|
182
|
-
return
|
|
183
|
-
|
|
184
|
-
# create the session.lock file
|
|
185
|
-
try:
|
|
186
|
-
# Try to open the file
|
|
187
|
-
lock = portalocker.Lock(
|
|
188
|
-
os.path.join(self.path, "session.lock"),
|
|
189
|
-
"wb+",
|
|
190
|
-
fail_when_locked=True,
|
|
191
|
-
)
|
|
192
|
-
lock_file: BinaryIO = lock.acquire() # type: ignore
|
|
193
|
-
except portalocker.LockException:
|
|
194
|
-
raise Exception(
|
|
195
|
-
f"Could not acquire session.lock. The world may be open somewhere else."
|
|
196
|
-
)
|
|
197
|
-
else:
|
|
198
|
-
# write the current time to the file
|
|
199
|
-
lock_time = time.time()
|
|
200
|
-
lock_file.write(struct.pack(">Q", int(lock_time * 1000)))
|
|
201
|
-
|
|
202
|
-
# flush the changes to disk
|
|
203
|
-
lock_file.flush()
|
|
204
|
-
os.fsync(lock_file.fileno())
|
|
205
|
-
|
|
206
|
-
packs = []
|
|
207
|
-
enabled_packs = (
|
|
208
|
-
self.level_dat.compound.get_compound("Data", CompoundTag())
|
|
209
|
-
.get_compound("DataPacks", CompoundTag())
|
|
210
|
-
.get_list("Enabled", ListTag())
|
|
211
|
-
)
|
|
212
|
-
for pack in enabled_packs:
|
|
213
|
-
if isinstance(pack, StringTag):
|
|
214
|
-
pack_name: str = pack.py_str
|
|
215
|
-
if pack_name == "vanilla":
|
|
216
|
-
pass
|
|
217
|
-
elif pack_name.startswith("file/"):
|
|
218
|
-
path = os.path.join(self.path, "datapacks", pack_name[5:])
|
|
219
|
-
if DataPack.is_path_valid(path):
|
|
220
|
-
packs.append(DataPack(path))
|
|
221
|
-
data_pack = DataPackManager(packs)
|
|
222
|
-
|
|
223
|
-
self._raw_open_data = JavaRawLevelOpenData(
|
|
224
|
-
self, lock_file, lock_time, data_pack
|
|
225
|
-
)
|
|
226
|
-
self.opened.emit()
|
|
227
|
-
|
|
228
|
-
closed = Signal[()]()
|
|
229
|
-
|
|
230
|
-
def close(self) -> None:
|
|
231
|
-
"""Close the raw level."""
|
|
232
|
-
if not self.is_open():
|
|
233
|
-
return
|
|
234
|
-
open_data = self._o
|
|
235
|
-
portalocker.unlock(open_data.lock_file)
|
|
236
|
-
open_data.lock_file.close()
|
|
237
|
-
open_data.detach_back_reference()
|
|
238
|
-
self._raw_open_data = None
|
|
239
|
-
self.closed.emit()
|
|
240
|
-
|
|
241
|
-
@property
|
|
242
|
-
def path(self) -> str:
|
|
243
|
-
return self._path
|
|
244
|
-
|
|
245
|
-
@property
|
|
246
|
-
def level_dat(self) -> NamedTag:
|
|
247
|
-
"""Get the level.dat file for the world"""
|
|
248
|
-
return copy.deepcopy(self._level_dat)
|
|
249
|
-
|
|
250
|
-
@level_dat.setter
|
|
251
|
-
def level_dat(self, level_dat: NamedTag) -> None:
|
|
252
|
-
if not isinstance(level_dat, NamedTag):
|
|
253
|
-
raise TypeError
|
|
254
|
-
if not self.is_open():
|
|
255
|
-
raise RuntimeError("Level is not open.")
|
|
256
|
-
self._level_dat = level_dat = copy.deepcopy(level_dat)
|
|
257
|
-
self._update_data_version()
|
|
258
|
-
level_dat.save_to(os.path.join(self.path, "level.dat"))
|
|
259
|
-
|
|
260
|
-
@property
|
|
261
|
-
def platform(self) -> str:
|
|
262
|
-
return "java"
|
|
263
|
-
|
|
264
|
-
@property
|
|
265
|
-
def data_version(self) -> VersionNumber:
|
|
266
|
-
"""
|
|
267
|
-
The game data version that the level was last opened in.
|
|
268
|
-
This is used to determine the data format to save in.
|
|
269
|
-
"""
|
|
270
|
-
return self._data_version
|
|
271
|
-
|
|
272
|
-
@property
|
|
273
|
-
def modified_time(self) -> float:
|
|
274
|
-
"""Unix timestamp of when the level was last modified."""
|
|
275
|
-
return (
|
|
276
|
-
self.level_dat.compound.get_compound("Data", CompoundTag())
|
|
277
|
-
.get_long("LastPlayed", LongTag())
|
|
278
|
-
.py_int
|
|
279
|
-
/ 1000
|
|
280
|
-
)
|
|
281
|
-
|
|
282
|
-
@property
|
|
283
|
-
def level_name(self) -> str:
|
|
284
|
-
return (
|
|
285
|
-
self._level_dat.compound.get_compound("Data", CompoundTag())
|
|
286
|
-
.get_string("LevelName", StringTag("Undefined"))
|
|
287
|
-
.py_str
|
|
288
|
-
)
|
|
289
|
-
|
|
290
|
-
@level_name.setter
|
|
291
|
-
def level_name(self, value: str) -> None:
|
|
292
|
-
level_dat = self.level_dat
|
|
293
|
-
level_dat.compound.setdefault_compound("Data")["LevelName"] = StringTag(value)
|
|
294
|
-
self.level_dat = level_dat
|
|
295
|
-
|
|
296
|
-
def _get_dimension_bounds(self, dimension_type_str: DimensionId) -> SelectionGroup:
|
|
297
|
-
if self._data_version >= VersionNumber(2709): # This number might be smaller
|
|
298
|
-
# If in a version that supports custom height data packs
|
|
299
|
-
dimension_settings = (
|
|
300
|
-
self.level_dat.compound.get_compound("Data", CompoundTag())
|
|
301
|
-
.get_compound("WorldGenSettings", CompoundTag())
|
|
302
|
-
.get_compound("dimensions", CompoundTag())
|
|
303
|
-
.get_compound(dimension_type_str, CompoundTag())
|
|
304
|
-
)
|
|
305
|
-
|
|
306
|
-
# "type" can be a reference (string) or inline (compound) dimension-type data.
|
|
307
|
-
dimension_type = dimension_settings.get("type")
|
|
308
|
-
|
|
309
|
-
if isinstance(dimension_type, StringTag):
|
|
310
|
-
# Reference type. Load the dimension data
|
|
311
|
-
dimension_type_str = dimension_type.py_str
|
|
312
|
-
if ":" in dimension_type_str:
|
|
313
|
-
namespace, base_name = dimension_type_str.split(":", 1)
|
|
314
|
-
else:
|
|
315
|
-
namespace = "minecraft"
|
|
316
|
-
base_name = dimension_type_str
|
|
317
|
-
name_tuple = namespace, base_name
|
|
318
|
-
|
|
319
|
-
# First try and load the reference from the data pack and then from defaults
|
|
320
|
-
dimension_path = f"data/{namespace}/dimension_type/{base_name}.json"
|
|
321
|
-
if self._o.data_pack.has_file(dimension_path):
|
|
322
|
-
with self._o.data_pack.open(dimension_path) as d:
|
|
323
|
-
try:
|
|
324
|
-
dimension_settings_json = json.load(d)
|
|
325
|
-
except json.JSONDecodeError:
|
|
326
|
-
pass
|
|
327
|
-
else:
|
|
328
|
-
if "min_y" in dimension_settings_json and isinstance(
|
|
329
|
-
dimension_settings_json["min_y"], int
|
|
330
|
-
):
|
|
331
|
-
min_y = dimension_settings_json["min_y"]
|
|
332
|
-
if min_y % 16:
|
|
333
|
-
min_y = 16 * (min_y // 16)
|
|
334
|
-
else:
|
|
335
|
-
min_y = 0
|
|
336
|
-
if "height" in dimension_settings_json and isinstance(
|
|
337
|
-
dimension_settings_json["height"], int
|
|
338
|
-
):
|
|
339
|
-
height = dimension_settings_json["height"]
|
|
340
|
-
if height % 16:
|
|
341
|
-
height = -16 * (-height // 16)
|
|
342
|
-
else:
|
|
343
|
-
height = 256
|
|
344
|
-
|
|
345
|
-
return SelectionGroup(
|
|
346
|
-
SelectionBox(
|
|
347
|
-
(-30_000_000, min_y, -30_000_000),
|
|
348
|
-
(30_000_000, min_y + height, 30_000_000),
|
|
349
|
-
)
|
|
350
|
-
)
|
|
351
|
-
|
|
352
|
-
elif name_tuple in {
|
|
353
|
-
("minecraft", "overworld"),
|
|
354
|
-
("minecraft", "overworld_caves"),
|
|
355
|
-
}:
|
|
356
|
-
if self.data_version >= VersionNumber(2825):
|
|
357
|
-
# If newer than the height change version
|
|
358
|
-
return SelectionGroup(
|
|
359
|
-
SelectionBox(
|
|
360
|
-
(-30_000_000, -64, -30_000_000),
|
|
361
|
-
(30_000_000, 320, 30_000_000),
|
|
362
|
-
)
|
|
363
|
-
)
|
|
364
|
-
else:
|
|
365
|
-
return DefaultSelection
|
|
366
|
-
elif name_tuple in {
|
|
367
|
-
("minecraft", "the_nether"),
|
|
368
|
-
("minecraft", "the_end"),
|
|
369
|
-
}:
|
|
370
|
-
return DefaultSelection
|
|
371
|
-
else:
|
|
372
|
-
log.error(f"Could not find dimension_type {':'.join(name_tuple)}")
|
|
373
|
-
|
|
374
|
-
elif isinstance(dimension_type, CompoundTag):
|
|
375
|
-
# Inline type
|
|
376
|
-
dimension_type_compound = dimension_type
|
|
377
|
-
min_y = (
|
|
378
|
-
dimension_type_compound.get_int("min_y", IntTag()).py_int // 16
|
|
379
|
-
) * 16
|
|
380
|
-
height = (
|
|
381
|
-
-dimension_type_compound.get_int("height", IntTag(256)).py_int // 16
|
|
382
|
-
) * -16
|
|
383
|
-
return SelectionGroup(
|
|
384
|
-
SelectionBox(
|
|
385
|
-
(-30_000_000, min_y, -30_000_000),
|
|
386
|
-
(30_000_000, min_y + height, 30_000_000),
|
|
387
|
-
)
|
|
388
|
-
)
|
|
389
|
-
else:
|
|
390
|
-
log.error(
|
|
391
|
-
f'level_dat["Data"]["WorldGenSettings"]["dimensions"]["{dimension_type_str}"]["type"] was not a StringTag or CompoundTag.'
|
|
392
|
-
)
|
|
393
|
-
|
|
394
|
-
# Return the default if nothing else returned
|
|
395
|
-
return DefaultSelection
|
|
396
|
-
|
|
397
|
-
def _register_dimension(
|
|
398
|
-
self,
|
|
399
|
-
relative_dimension_path: InternalDimensionId,
|
|
400
|
-
dimension_name: DimensionId,
|
|
401
|
-
) -> None:
|
|
402
|
-
"""
|
|
403
|
-
Register a new dimension.
|
|
404
|
-
|
|
405
|
-
:param relative_dimension_path: The relative path to the dimension directory from the world root.
|
|
406
|
-
"" for the world root.
|
|
407
|
-
:param dimension_name: The name of the dimension shown to the user
|
|
408
|
-
"""
|
|
409
|
-
if relative_dimension_path:
|
|
410
|
-
path = os.path.join(self.path, relative_dimension_path)
|
|
411
|
-
else:
|
|
412
|
-
path = self.path
|
|
413
|
-
|
|
414
|
-
if (
|
|
415
|
-
relative_dimension_path not in self._o.dimensions
|
|
416
|
-
and dimension_name not in self._o.dimension_ids
|
|
417
|
-
):
|
|
418
|
-
self._o.dimension_ids[dimension_name] = relative_dimension_path
|
|
419
|
-
self._o.dimensions[relative_dimension_path] = JavaRawDimension(
|
|
420
|
-
self._o.back_reference,
|
|
421
|
-
# TODO: The data version can change while the level is open.
|
|
422
|
-
# That may cause problems with this.
|
|
423
|
-
AnvilDimension(
|
|
424
|
-
path,
|
|
425
|
-
mcc=self.data_version > VersionNumber(2203),
|
|
426
|
-
layers=("region",)
|
|
427
|
-
+ ("entities",) * (self.data_version >= VersionNumber(2681)),
|
|
428
|
-
),
|
|
429
|
-
relative_dimension_path,
|
|
430
|
-
dimension_name,
|
|
431
|
-
self._get_dimension_bounds(dimension_name),
|
|
432
|
-
# TODO: Is this data stored somewhere?
|
|
433
|
-
BlockStack(Block("java", VersionNumber(3700), "minecraft", "air")),
|
|
434
|
-
(
|
|
435
|
-
Biome("java", VersionNumber(3700), "minecraft", "nether_wastes")
|
|
436
|
-
if dimension_name == THE_NETHER
|
|
437
|
-
else (
|
|
438
|
-
Biome("java", VersionNumber(3700), "minecraft", "the_end")
|
|
439
|
-
if dimension_name == THE_END
|
|
440
|
-
else Biome("java", VersionNumber(3700), "minecraft", "plains")
|
|
441
|
-
)
|
|
442
|
-
),
|
|
443
|
-
)
|
|
444
|
-
|
|
445
|
-
def _find_dimensions(self) -> None:
|
|
446
|
-
with self._o.dimensions_lock:
|
|
447
|
-
if self._o.dimensions:
|
|
448
|
-
return
|
|
449
|
-
|
|
450
|
-
# load all the levels
|
|
451
|
-
self._register_dimension("", OVERWORLD)
|
|
452
|
-
self._register_dimension("DIM-1", THE_NETHER)
|
|
453
|
-
self._register_dimension("DIM1", THE_END)
|
|
454
|
-
|
|
455
|
-
for level_path in glob.glob(os.path.join(glob.escape(self.path), "DIM*")):
|
|
456
|
-
if os.path.isdir(level_path):
|
|
457
|
-
dir_name = os.path.basename(level_path)
|
|
458
|
-
if AnvilDimension.level_regex.fullmatch(dir_name) is None:
|
|
459
|
-
continue
|
|
460
|
-
self._register_dimension(dir_name, dir_name)
|
|
461
|
-
|
|
462
|
-
for region_path in glob.glob(
|
|
463
|
-
os.path.join(
|
|
464
|
-
glob.escape(self.path), "dimensions", "*", "*", "**", "region"
|
|
465
|
-
),
|
|
466
|
-
recursive=True,
|
|
467
|
-
):
|
|
468
|
-
if not os.path.isdir(region_path):
|
|
469
|
-
continue
|
|
470
|
-
dimension_path = os.path.dirname(region_path)
|
|
471
|
-
rel_dim_path = os.path.relpath(dimension_path, self.path)
|
|
472
|
-
_, dimension, *base_name = rel_dim_path.split(os.sep)
|
|
473
|
-
|
|
474
|
-
dimension_name = f"{dimension}:{'/'.join(base_name)}"
|
|
475
|
-
self._register_dimension(rel_dim_path, dimension_name)
|
|
476
|
-
|
|
477
|
-
def dimension_ids(self) -> frozenset[DimensionId]:
|
|
478
|
-
self._find_dimensions()
|
|
479
|
-
return frozenset(self._o.dimension_ids)
|
|
480
|
-
|
|
481
|
-
def get_dimension(self, dimension_id: DimensionId) -> JavaRawDimension:
|
|
482
|
-
self._find_dimensions()
|
|
483
|
-
internal_dimension_id = self._o.dimension_ids.get(dimension_id, dimension_id)
|
|
484
|
-
if internal_dimension_id not in self._o.dimensions:
|
|
485
|
-
raise RuntimeError(f"Dimension {dimension_id} does not exist")
|
|
486
|
-
return self._o.dimensions[internal_dimension_id]
|
|
487
|
-
|
|
488
|
-
def compact(self) -> None:
|
|
489
|
-
"""Compact all region files"""
|
|
490
|
-
for dimension_id in self.dimension_ids():
|
|
491
|
-
self.get_dimension(dimension_id).compact()
|
|
492
|
-
|
|
493
|
-
@property
|
|
494
|
-
def block_id_override(self) -> IdRegistry:
|
|
495
|
-
"""
|
|
496
|
-
A two-way map from hard coded numerical block id <-> block string.
|
|
497
|
-
This only stores overridden values. If the value is not present here you should check the translator.
|
|
498
|
-
"""
|
|
499
|
-
return self._o.block_id_override
|
|
500
|
-
|
|
501
|
-
@property
|
|
502
|
-
def biome_id_override(self) -> IdRegistry:
|
|
503
|
-
"""
|
|
504
|
-
A two-way map from hard coded numerical biome id <-> biome string.
|
|
505
|
-
This only stores overridden values. If the value is not present here you should check the translator.
|
|
506
|
-
"""
|
|
507
|
-
return self._o.biome_id_override
|