amulet-core 2.0a5__cp311-cp311-macosx_10_9_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of amulet-core might be problematic. Click here for more details.
- amulet/__init__.cpython-311-darwin.so +0 -0
- amulet/__init__.pyi +30 -0
- amulet/__pyinstaller/__init__.py +2 -0
- amulet/__pyinstaller/hook-amulet.py +4 -0
- amulet/_init.py +28 -0
- amulet/_version.py +21 -0
- amulet/biome.cpp +36 -0
- amulet/biome.hpp +43 -0
- amulet/biome.pyi +77 -0
- amulet/block.cpp +435 -0
- amulet/block.hpp +119 -0
- amulet/block.pyi +273 -0
- amulet/block_entity.cpp +12 -0
- amulet/block_entity.hpp +56 -0
- amulet/block_entity.pyi +80 -0
- amulet/chunk.cpp +16 -0
- amulet/chunk.hpp +99 -0
- amulet/chunk.pyi +30 -0
- amulet/chunk_/components/biome.py +155 -0
- amulet/chunk_/components/block_entity.py +117 -0
- amulet/chunk_/components/entity.py +64 -0
- amulet/chunk_/components/height_2d.py +16 -0
- amulet/chunk_components.pyi +95 -0
- amulet/collections.pyi +37 -0
- amulet/data_types.py +29 -0
- amulet/entity.py +180 -0
- amulet/errors.py +63 -0
- amulet/game/__init__.py +7 -0
- amulet/game/_game.py +152 -0
- amulet/game/_universal/__init__.py +1 -0
- amulet/game/_universal/_biome.py +17 -0
- amulet/game/_universal/_block.py +47 -0
- amulet/game/_universal/_version.py +68 -0
- amulet/game/abc/__init__.py +22 -0
- amulet/game/abc/_block_specification.py +150 -0
- amulet/game/abc/biome.py +213 -0
- amulet/game/abc/block.py +331 -0
- amulet/game/abc/game_version_container.py +25 -0
- amulet/game/abc/json_interface.py +27 -0
- amulet/game/abc/version.py +44 -0
- amulet/game/bedrock/__init__.py +1 -0
- amulet/game/bedrock/_biome.py +35 -0
- amulet/game/bedrock/_block.py +42 -0
- amulet/game/bedrock/_version.py +165 -0
- amulet/game/java/__init__.py +2 -0
- amulet/game/java/_biome.py +35 -0
- amulet/game/java/_block.py +60 -0
- amulet/game/java/_version.py +176 -0
- amulet/game/translate/__init__.py +12 -0
- amulet/game/translate/_functions/__init__.py +15 -0
- amulet/game/translate/_functions/_code_functions/__init__.py +0 -0
- amulet/game/translate/_functions/_code_functions/_text.py +553 -0
- amulet/game/translate/_functions/_code_functions/banner_pattern.py +67 -0
- amulet/game/translate/_functions/_code_functions/bedrock_chest_connection.py +152 -0
- amulet/game/translate/_functions/_code_functions/bedrock_moving_block_pos.py +88 -0
- amulet/game/translate/_functions/_code_functions/bedrock_sign.py +152 -0
- amulet/game/translate/_functions/_code_functions/bedrock_skull_rotation.py +16 -0
- amulet/game/translate/_functions/_code_functions/custom_name.py +146 -0
- amulet/game/translate/_functions/_frozen.py +66 -0
- amulet/game/translate/_functions/_state.py +54 -0
- amulet/game/translate/_functions/_typing.py +98 -0
- amulet/game/translate/_functions/abc.py +116 -0
- amulet/game/translate/_functions/carry_nbt.py +160 -0
- amulet/game/translate/_functions/carry_properties.py +80 -0
- amulet/game/translate/_functions/code.py +143 -0
- amulet/game/translate/_functions/map_block_name.py +66 -0
- amulet/game/translate/_functions/map_nbt.py +111 -0
- amulet/game/translate/_functions/map_properties.py +93 -0
- amulet/game/translate/_functions/multiblock.py +112 -0
- amulet/game/translate/_functions/new_block.py +42 -0
- amulet/game/translate/_functions/new_entity.py +43 -0
- amulet/game/translate/_functions/new_nbt.py +206 -0
- amulet/game/translate/_functions/new_properties.py +64 -0
- amulet/game/translate/_functions/sequence.py +51 -0
- amulet/game/translate/_functions/walk_input_nbt.py +331 -0
- amulet/game/translate/_translator.py +433 -0
- amulet/item.py +75 -0
- amulet/level/__init__.pyi +27 -0
- amulet/level/_load.py +100 -0
- amulet/level/abc/__init__.py +12 -0
- amulet/level/abc/_chunk_handle.py +335 -0
- amulet/level/abc/_dimension.py +86 -0
- amulet/level/abc/_history/__init__.py +1 -0
- amulet/level/abc/_history/_cache.py +224 -0
- amulet/level/abc/_history/_history_manager.py +291 -0
- amulet/level/abc/_level/__init__.py +5 -0
- amulet/level/abc/_level/_compactable_level.py +10 -0
- amulet/level/abc/_level/_creatable_level.py +29 -0
- amulet/level/abc/_level/_disk_level.py +17 -0
- amulet/level/abc/_level/_level.py +453 -0
- amulet/level/abc/_level/_loadable_level.py +42 -0
- amulet/level/abc/_player_storage.py +7 -0
- amulet/level/abc/_raw_level.py +187 -0
- amulet/level/abc/_registry.py +40 -0
- amulet/level/bedrock/__init__.py +2 -0
- amulet/level/bedrock/_chunk_handle.py +19 -0
- amulet/level/bedrock/_dimension.py +22 -0
- amulet/level/bedrock/_level.py +187 -0
- amulet/level/bedrock/_raw/__init__.py +5 -0
- amulet/level/bedrock/_raw/_actor_counter.py +53 -0
- amulet/level/bedrock/_raw/_chunk.py +54 -0
- amulet/level/bedrock/_raw/_chunk_decode.py +668 -0
- amulet/level/bedrock/_raw/_chunk_encode.py +602 -0
- amulet/level/bedrock/_raw/_constant.py +9 -0
- amulet/level/bedrock/_raw/_dimension.py +343 -0
- amulet/level/bedrock/_raw/_level.py +463 -0
- amulet/level/bedrock/_raw/_level_dat.py +90 -0
- amulet/level/bedrock/_raw/_typing.py +6 -0
- amulet/level/bedrock/_raw/leveldb_chunk_versions.py +83 -0
- amulet/level/bedrock/chunk/__init__.py +1 -0
- amulet/level/bedrock/chunk/_chunk.py +126 -0
- amulet/level/bedrock/chunk/components/__init__.py +0 -0
- amulet/level/bedrock/chunk/components/chunk_version.py +12 -0
- amulet/level/bedrock/chunk/components/finalised_state.py +13 -0
- amulet/level/bedrock/chunk/components/raw_chunk.py +15 -0
- amulet/level/construction/__init__.py +0 -0
- amulet/level/java/__init__.pyi +21 -0
- amulet/level/java/_chunk_handle.py +17 -0
- amulet/level/java/_chunk_handle.pyi +15 -0
- amulet/level/java/_dimension.py +20 -0
- amulet/level/java/_dimension.pyi +13 -0
- amulet/level/java/_level.py +184 -0
- amulet/level/java/_level.pyi +120 -0
- amulet/level/java/_raw/__init__.pyi +19 -0
- amulet/level/java/_raw/_chunk.pyi +23 -0
- amulet/level/java/_raw/_chunk_decode.py +561 -0
- amulet/level/java/_raw/_chunk_encode.py +463 -0
- amulet/level/java/_raw/_constant.py +9 -0
- amulet/level/java/_raw/_constant.pyi +20 -0
- amulet/level/java/_raw/_data_pack/__init__.py +2 -0
- amulet/level/java/_raw/_data_pack/__init__.pyi +8 -0
- amulet/level/java/_raw/_data_pack/data_pack.py +241 -0
- amulet/level/java/_raw/_data_pack/data_pack.pyi +197 -0
- amulet/level/java/_raw/_data_pack/data_pack_manager.py +77 -0
- amulet/level/java/_raw/_data_pack/data_pack_manager.pyi +75 -0
- amulet/level/java/_raw/_dimension.py +86 -0
- amulet/level/java/_raw/_dimension.pyi +72 -0
- amulet/level/java/_raw/_level.py +507 -0
- amulet/level/java/_raw/_level.pyi +238 -0
- amulet/level/java/_raw/_typing.py +3 -0
- amulet/level/java/_raw/_typing.pyi +5 -0
- amulet/level/java/anvil/__init__.py +2 -0
- amulet/level/java/anvil/__init__.pyi +11 -0
- amulet/level/java/anvil/_dimension.py +170 -0
- amulet/level/java/anvil/_dimension.pyi +109 -0
- amulet/level/java/anvil/_region.py +421 -0
- amulet/level/java/anvil/_region.pyi +197 -0
- amulet/level/java/anvil/_sector_manager.py +223 -0
- amulet/level/java/anvil/_sector_manager.pyi +142 -0
- amulet/level/java/chunk.pyi +81 -0
- amulet/level/java/chunk_/_chunk.py +260 -0
- amulet/level/java/chunk_/components/inhabited_time.py +12 -0
- amulet/level/java/chunk_/components/last_update.py +12 -0
- amulet/level/java/chunk_/components/legacy_version.py +12 -0
- amulet/level/java/chunk_/components/light_populated.py +12 -0
- amulet/level/java/chunk_/components/named_height_2d.py +37 -0
- amulet/level/java/chunk_/components/status.py +11 -0
- amulet/level/java/chunk_/components/terrain_populated.py +12 -0
- amulet/level/java/chunk_components.pyi +22 -0
- amulet/level/java/long_array.pyi +38 -0
- amulet/level/java_forge/__init__.py +0 -0
- amulet/level/mcstructure/__init__.py +0 -0
- amulet/level/nbt/__init__.py +0 -0
- amulet/level/schematic/__init__.py +0 -0
- amulet/level/sponge_schematic/__init__.py +0 -0
- amulet/level/temporary_level/__init__.py +1 -0
- amulet/level/temporary_level/_level.py +16 -0
- amulet/palette/__init__.pyi +8 -0
- amulet/palette/biome_palette.pyi +45 -0
- amulet/palette/block_palette.pyi +45 -0
- amulet/player.py +64 -0
- amulet/py.typed +0 -0
- amulet/selection/__init__.py +2 -0
- amulet/selection/abstract_selection.py +342 -0
- amulet/selection/box.py +852 -0
- amulet/selection/group.py +481 -0
- amulet/utils/__init__.pyi +28 -0
- amulet/utils/call_spec/__init__.py +24 -0
- amulet/utils/call_spec/__init__.pyi +53 -0
- amulet/utils/call_spec/_call_spec.py +262 -0
- amulet/utils/call_spec/_call_spec.pyi +272 -0
- amulet/utils/format_utils.py +41 -0
- amulet/utils/generator.py +18 -0
- amulet/utils/matrix.py +243 -0
- amulet/utils/matrix.pyi +177 -0
- amulet/utils/numpy.pyi +11 -0
- amulet/utils/numpy_helpers.py +19 -0
- amulet/utils/shareable_lock.py +335 -0
- amulet/utils/shareable_lock.pyi +190 -0
- amulet/utils/signal/__init__.py +10 -0
- amulet/utils/signal/__init__.pyi +25 -0
- amulet/utils/signal/_signal.py +228 -0
- amulet/utils/signal/_signal.pyi +84 -0
- amulet/utils/task_manager.py +235 -0
- amulet/utils/task_manager.pyi +168 -0
- amulet/utils/typed_property.py +111 -0
- amulet/utils/typing.py +4 -0
- amulet/utils/typing.pyi +6 -0
- amulet/utils/weakref.py +70 -0
- amulet/utils/weakref.pyi +50 -0
- amulet/utils/world_utils.py +102 -0
- amulet/utils/world_utils.pyi +109 -0
- amulet/version.cpp +136 -0
- amulet/version.hpp +142 -0
- amulet/version.pyi +94 -0
- amulet_core-2.0a5.dist-info/METADATA +103 -0
- amulet_core-2.0a5.dist-info/RECORD +210 -0
- amulet_core-2.0a5.dist-info/WHEEL +5 -0
- amulet_core-2.0a5.dist-info/entry_points.txt +2 -0
- amulet_core-2.0a5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TypeVar, Any, Generic, Callable, overload
|
|
3
|
+
|
|
4
|
+
GetT = TypeVar("GetT")
|
|
5
|
+
SetT = TypeVar("SetT")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TypedProperty(Generic[GetT, SetT]):
|
|
9
|
+
"""
|
|
10
|
+
Type hinting with the vanilla property does not support having a different type on the setter.
|
|
11
|
+
See https://github.com/python/mypy/issues/3004
|
|
12
|
+
This is a custom property implementation that supports independently typing the getter and setter to appease mypy.
|
|
13
|
+
|
|
14
|
+
Note that the getter, setter and deleter return the method they were given and not a property instance.
|
|
15
|
+
This was to appease mypy complaining about overriding variables.
|
|
16
|
+
This has a side effect that a setter can be used as a setter or the method
|
|
17
|
+
|
|
18
|
+
>>> class MyClass:
|
|
19
|
+
>>> def __init__(self) -> None:
|
|
20
|
+
>>> self._value = 1
|
|
21
|
+
>>>
|
|
22
|
+
>>> @TypedProperty[int, int | float]
|
|
23
|
+
>>> def value(self) -> int:
|
|
24
|
+
>>> return self._value
|
|
25
|
+
>>>
|
|
26
|
+
>>> @value.setter
|
|
27
|
+
>>> def set_value(self, val: int | float) -> None:
|
|
28
|
+
>>> self._value = int(val)
|
|
29
|
+
>>>
|
|
30
|
+
>>> @value.deleter
|
|
31
|
+
>>> def del_value(self) -> None:
|
|
32
|
+
>>> del self._value
|
|
33
|
+
>>>
|
|
34
|
+
>>>
|
|
35
|
+
>>> inst = MyClass()
|
|
36
|
+
>>> assert inst.value == 1
|
|
37
|
+
>>> inst.value = 2
|
|
38
|
+
>>> assert inst.value == 2
|
|
39
|
+
>>> inst.set_value(3)
|
|
40
|
+
>>> assert inst.value == 3
|
|
41
|
+
>>> del inst.value
|
|
42
|
+
>>> try:
|
|
43
|
+
>>> inst.value
|
|
44
|
+
>>> except AttributeError:
|
|
45
|
+
>>> pass
|
|
46
|
+
>>> else:
|
|
47
|
+
>>> raise Exception
|
|
48
|
+
>>> inst.value = 4
|
|
49
|
+
>>> assert inst.value == 4
|
|
50
|
+
|
|
51
|
+
If you want the original methods to be private then just prefix them with an underscore.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
fget: Callable[[Any], GetT] | None
|
|
55
|
+
fset: Callable[[Any, SetT], None] | None
|
|
56
|
+
fdel: Callable[[Any], None] | None
|
|
57
|
+
|
|
58
|
+
def __init__(
|
|
59
|
+
self,
|
|
60
|
+
fget: Callable[[Any], GetT] | None = None,
|
|
61
|
+
fset: Callable[[Any, SetT], None] | None = None,
|
|
62
|
+
fdel: Callable[[Any], None] | None = None,
|
|
63
|
+
doc: str | None = None,
|
|
64
|
+
) -> None:
|
|
65
|
+
self.fget = fget
|
|
66
|
+
self.fset = fset
|
|
67
|
+
self.fdel = fdel
|
|
68
|
+
if doc is None and fget is not None:
|
|
69
|
+
doc = fget.__doc__
|
|
70
|
+
self.__doc__ = doc
|
|
71
|
+
self._name = ""
|
|
72
|
+
|
|
73
|
+
def __set_name__(self, owner: Any, name: str) -> None:
|
|
74
|
+
self._name = name
|
|
75
|
+
|
|
76
|
+
@overload
|
|
77
|
+
def __get__(self, obj: None, objtype: None) -> TypedProperty[GetT, SetT]: ...
|
|
78
|
+
|
|
79
|
+
@overload
|
|
80
|
+
def __get__(self, obj: object, objtype: type[object]) -> GetT: ...
|
|
81
|
+
|
|
82
|
+
def __get__(
|
|
83
|
+
self, obj: Any, objtype: Any = None
|
|
84
|
+
) -> GetT | TypedProperty[GetT, SetT]:
|
|
85
|
+
if obj is None:
|
|
86
|
+
return self
|
|
87
|
+
if self.fget is None:
|
|
88
|
+
raise AttributeError(f"property '{self._name}' has no getter")
|
|
89
|
+
return self.fget(obj)
|
|
90
|
+
|
|
91
|
+
def __set__(self, obj: Any, value: SetT) -> None:
|
|
92
|
+
if self.fset is None:
|
|
93
|
+
raise AttributeError(f"property '{self._name}' has no setter")
|
|
94
|
+
self.fset(obj, value)
|
|
95
|
+
|
|
96
|
+
def __delete__(self, obj: Any) -> None:
|
|
97
|
+
if self.fdel is None:
|
|
98
|
+
raise AttributeError(f"property '{self._name}' has no deleter")
|
|
99
|
+
self.fdel(obj)
|
|
100
|
+
|
|
101
|
+
def getter(self, fget: Callable[[Any], GetT]) -> Callable[[Any], GetT]:
|
|
102
|
+
self.fget = fget
|
|
103
|
+
return fget
|
|
104
|
+
|
|
105
|
+
def setter(self, fset: Callable[[Any, SetT], None]) -> Callable[[Any, SetT], None]:
|
|
106
|
+
self.fset = fset
|
|
107
|
+
return fset
|
|
108
|
+
|
|
109
|
+
def deleter(self, fdel: Callable[[Any], None]) -> Callable[[Any], None]:
|
|
110
|
+
self.fdel = fdel
|
|
111
|
+
return fdel
|
amulet/utils/typing.py
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# There are cases where it would be useful to type hint a class that must inherit from two or more ABCs.
|
|
2
|
+
# Python doesn't currently have an intersection type but all cases that need it should refer here to make renaming
|
|
3
|
+
# easier if Python implements it.
|
|
4
|
+
from typing import Union as Intersection # noqa
|
amulet/utils/typing.pyi
ADDED
amulet/utils/weakref.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Extension to the builtin weakref module."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from typing import Any, TypeVar, Generic, Callable, final
|
|
5
|
+
from weakref import WeakMethod as _WeakMethod, ReferenceType as _ReferenceType
|
|
6
|
+
|
|
7
|
+
T = TypeVar("T")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Classes have an __del__ method to run code at object destruction.
|
|
11
|
+
# This is usually sufficient if the object gets deleted before the interpreter exits.
|
|
12
|
+
# In some cases global variables are set to None causing the __del__ to fail if run after interpreter shutdown.
|
|
13
|
+
# I have noticed this while debugging.
|
|
14
|
+
#
|
|
15
|
+
# In the following example when debugging sys is None when __del__ is called after interpreter shutdown.
|
|
16
|
+
#
|
|
17
|
+
# >>> import sys
|
|
18
|
+
# >>>
|
|
19
|
+
# >>> class Cls:
|
|
20
|
+
# >>> def __init__(self) -> None:
|
|
21
|
+
# >>> self._sys_modules = sys.modules
|
|
22
|
+
# >>> print(self._sys_modules)
|
|
23
|
+
# >>>
|
|
24
|
+
# >>> def __del__(self) -> None:
|
|
25
|
+
# >>> print(self._sys_modules)
|
|
26
|
+
# >>> print(sys)
|
|
27
|
+
# >>>
|
|
28
|
+
# >>> t = Cls()
|
|
29
|
+
#
|
|
30
|
+
# weakref.finalize takes care of this. It can be manually called in the __del__ method if the object is garbage
|
|
31
|
+
# collected before interpreter shutdown or automatically run at interpreter exit. It can only be called once.
|
|
32
|
+
# It must be given a weak method otherwise the instance will be kept alive until interpreter exit.
|
|
33
|
+
# weakref.WeakMethod is not directly callable so CallableWeakMethod is implemented to allow this.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@final
|
|
37
|
+
class CallableWeakMethod(_WeakMethod):
|
|
38
|
+
"""
|
|
39
|
+
A wrapper around WeakMethod that makes the method directly callable.
|
|
40
|
+
If the method no longer exists, this does nothing.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __call__(self, *args: Any, **kwargs: Any) -> Any:
|
|
44
|
+
meth = super().__call__()
|
|
45
|
+
if meth is not None:
|
|
46
|
+
return meth(*args, **kwargs)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@final
|
|
50
|
+
class DetachableWeakRef(Generic[T]):
|
|
51
|
+
"""A weak reference that can be detached by the creator before the object is deleted."""
|
|
52
|
+
|
|
53
|
+
_ref: Callable[[], T | None]
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def new(cls, obj: T) -> tuple[DetachableWeakRef[T], Callable[[], None]]:
|
|
57
|
+
"""Get a new weak reference and a callable to detach the object.
|
|
58
|
+
Once called the reference will always return None.
|
|
59
|
+
"""
|
|
60
|
+
self = cls(obj)
|
|
61
|
+
return self, self._detach
|
|
62
|
+
|
|
63
|
+
def __init__(self, obj: T) -> None:
|
|
64
|
+
self._ref = _ReferenceType(obj)
|
|
65
|
+
|
|
66
|
+
def __call__(self) -> T | None:
|
|
67
|
+
return self._ref()
|
|
68
|
+
|
|
69
|
+
def _detach(self) -> None:
|
|
70
|
+
self._ref = lambda: None
|
amulet/utils/weakref.pyi
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Extension to the builtin weakref module.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import typing
|
|
8
|
+
import weakref
|
|
9
|
+
from typing import Any, Generic, TypeVar, final
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"Any",
|
|
13
|
+
"CallableWeakMethod",
|
|
14
|
+
"DetachableWeakRef",
|
|
15
|
+
"Generic",
|
|
16
|
+
"T",
|
|
17
|
+
"TypeVar",
|
|
18
|
+
"final",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
class CallableWeakMethod(weakref.WeakMethod):
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
A wrapper around WeakMethod that makes the method directly callable.
|
|
25
|
+
If the method no longer exists, this does nothing.
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
__final__: typing.ClassVar[bool] = True
|
|
30
|
+
def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> typing.Any: ...
|
|
31
|
+
|
|
32
|
+
class DetachableWeakRef(typing.Generic):
|
|
33
|
+
"""
|
|
34
|
+
A weak reference that can be detached by the creator before the object is deleted.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
__final__: typing.ClassVar[bool] = True
|
|
38
|
+
@classmethod
|
|
39
|
+
def new(cls, obj: T) -> tuple[DetachableWeakRef[T], typing.Callable[[], None]]:
|
|
40
|
+
"""
|
|
41
|
+
Get a new weak reference and a callable to detach the object.
|
|
42
|
+
Once called the reference will always return None.
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __call__(self) -> T | None: ...
|
|
47
|
+
def __init__(self, obj: T) -> None: ...
|
|
48
|
+
def _detach(self) -> None: ...
|
|
49
|
+
|
|
50
|
+
T: typing.TypeVar # value = ~T
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
from typing import Tuple, Optional
|
|
5
|
+
import numpy
|
|
6
|
+
from numpy import ndarray, zeros, uint8
|
|
7
|
+
from amulet.data_types import ChunkCoordinates
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def block_coords_to_chunk_coords(
|
|
11
|
+
*args: int, sub_chunk_size: int = 16
|
|
12
|
+
) -> Tuple[int, ...]:
|
|
13
|
+
"""
|
|
14
|
+
Converts the supplied block coordinates into chunk coordinates
|
|
15
|
+
|
|
16
|
+
:param args: The coordinate of the block(s)
|
|
17
|
+
:param sub_chunk_size: The dimension of the chunk (Optional. Default 16)
|
|
18
|
+
:return: The resulting chunk coordinates in (x, z) order
|
|
19
|
+
"""
|
|
20
|
+
return tuple(int(math.floor(coord / sub_chunk_size)) for coord in args)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def chunk_coords_to_block_coords(
|
|
24
|
+
x: int, z: int, chunk_x_size: int = 16, chunk_z_size: int = 16
|
|
25
|
+
) -> ChunkCoordinates:
|
|
26
|
+
"""
|
|
27
|
+
Converts the supplied chunk coordinates into block coordinates
|
|
28
|
+
|
|
29
|
+
:param x: The x coordinate of the chunk
|
|
30
|
+
:param z: The z coordinate of the chunk
|
|
31
|
+
:param chunk_x_size: The dimension of the chunk in the x direction (Optional. Default 16)
|
|
32
|
+
:param chunk_z_size: The dimension of the chunk in the z direction (Optional. Default 16)
|
|
33
|
+
:return: The resulting block coordinates in (x, z) order
|
|
34
|
+
"""
|
|
35
|
+
return x * chunk_x_size, z * chunk_z_size
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def chunk_coords_to_region_coords(cx: int, cz: int) -> ChunkCoordinates:
|
|
39
|
+
"""
|
|
40
|
+
Converts the supplied chunk coordinates into region coordinates
|
|
41
|
+
|
|
42
|
+
:param cx: The x coordinate of the chunk
|
|
43
|
+
:param cz: The z coordinate of the chunk
|
|
44
|
+
:return: The resulting region coordinates in (x, z) order
|
|
45
|
+
"""
|
|
46
|
+
return cx >> 5, cz >> 5
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def region_coords_to_chunk_coords(rx: int, rz: int) -> ChunkCoordinates:
|
|
50
|
+
"""
|
|
51
|
+
Converts the supplied region coordinates into the minimum chunk coordinates of that region
|
|
52
|
+
|
|
53
|
+
:param rx: The x coordinate of the region
|
|
54
|
+
:param rz: The y coordinate of the region
|
|
55
|
+
:return: The resulting minimum chunk coordinates of that region in (x, z) order
|
|
56
|
+
"""
|
|
57
|
+
return rx << 5, rz << 5
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def blocks_slice_to_chunk_slice(
|
|
61
|
+
blocks_slice: slice, chunk_shape: int, chunk_coord: int
|
|
62
|
+
) -> slice:
|
|
63
|
+
"""
|
|
64
|
+
Converts the supplied blocks slice into chunk slice
|
|
65
|
+
|
|
66
|
+
:param blocks_slice: The slice of the blocks
|
|
67
|
+
:param chunk_shape: The shape of the chunk in this direction
|
|
68
|
+
:param chunk_coord: The coordinate of the chunk in this direction
|
|
69
|
+
:return: The resulting chunk slice
|
|
70
|
+
"""
|
|
71
|
+
return slice(
|
|
72
|
+
min(max(0, blocks_slice.start - chunk_coord * chunk_shape), chunk_shape),
|
|
73
|
+
min(max(0, blocks_slice.stop - chunk_coord * chunk_shape), chunk_shape),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def from_nibble_array(arr: ndarray) -> ndarray:
|
|
78
|
+
"""
|
|
79
|
+
Unpacks a flat nibble array into a full size numpy array
|
|
80
|
+
|
|
81
|
+
:param arr: The nibble array
|
|
82
|
+
:return: The resulting array
|
|
83
|
+
"""
|
|
84
|
+
shape = arr.size
|
|
85
|
+
|
|
86
|
+
new_arr = zeros((shape * 2), dtype=uint8)
|
|
87
|
+
|
|
88
|
+
new_arr[::2] = arr & 0xF
|
|
89
|
+
new_arr[1::2] = arr >> 4
|
|
90
|
+
|
|
91
|
+
return new_arr
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def to_nibble_array(arr: ndarray) -> ndarray:
|
|
95
|
+
"""
|
|
96
|
+
packs a full size numpy array into a nibble array.
|
|
97
|
+
|
|
98
|
+
:param arr: Full numpy array
|
|
99
|
+
:return: The nibble array
|
|
100
|
+
"""
|
|
101
|
+
arr = arr.ravel()
|
|
102
|
+
return (arr[::2] + (arr[1::2] << 4)).astype(uint8) # type: ignore
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import math as math
|
|
4
|
+
import types
|
|
5
|
+
|
|
6
|
+
import numpy as numpy
|
|
7
|
+
from numpy import ndarray, uint8, zeros
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"ChunkCoordinates",
|
|
11
|
+
"block_coords_to_chunk_coords",
|
|
12
|
+
"blocks_slice_to_chunk_slice",
|
|
13
|
+
"chunk_coords_to_block_coords",
|
|
14
|
+
"chunk_coords_to_region_coords",
|
|
15
|
+
"from_nibble_array",
|
|
16
|
+
"math",
|
|
17
|
+
"ndarray",
|
|
18
|
+
"numpy",
|
|
19
|
+
"region_coords_to_chunk_coords",
|
|
20
|
+
"to_nibble_array",
|
|
21
|
+
"uint8",
|
|
22
|
+
"zeros",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
def block_coords_to_chunk_coords(
|
|
26
|
+
*args: int, sub_chunk_size: int = 16
|
|
27
|
+
) -> tuple[int, ...]:
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
Converts the supplied block coordinates into chunk coordinates
|
|
31
|
+
|
|
32
|
+
:param args: The coordinate of the block(s)
|
|
33
|
+
:param sub_chunk_size: The dimension of the chunk (Optional. Default 16)
|
|
34
|
+
:return: The resulting chunk coordinates in (x, z) order
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def blocks_slice_to_chunk_slice(
|
|
39
|
+
blocks_slice: slice, chunk_shape: int, chunk_coord: int
|
|
40
|
+
) -> slice:
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
Converts the supplied blocks slice into chunk slice
|
|
44
|
+
|
|
45
|
+
:param blocks_slice: The slice of the blocks
|
|
46
|
+
:param chunk_shape: The shape of the chunk in this direction
|
|
47
|
+
:param chunk_coord: The coordinate of the chunk in this direction
|
|
48
|
+
:return: The resulting chunk slice
|
|
49
|
+
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def chunk_coords_to_block_coords(
|
|
53
|
+
x: int, z: int, chunk_x_size: int = 16, chunk_z_size: int = 16
|
|
54
|
+
) -> ChunkCoordinates:
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
Converts the supplied chunk coordinates into block coordinates
|
|
58
|
+
|
|
59
|
+
:param x: The x coordinate of the chunk
|
|
60
|
+
:param z: The z coordinate of the chunk
|
|
61
|
+
:param chunk_x_size: The dimension of the chunk in the x direction (Optional. Default 16)
|
|
62
|
+
:param chunk_z_size: The dimension of the chunk in the z direction (Optional. Default 16)
|
|
63
|
+
:return: The resulting block coordinates in (x, z) order
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
def chunk_coords_to_region_coords(cx: int, cz: int) -> ChunkCoordinates:
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
Converts the supplied chunk coordinates into region coordinates
|
|
71
|
+
|
|
72
|
+
:param cx: The x coordinate of the chunk
|
|
73
|
+
:param cz: The z coordinate of the chunk
|
|
74
|
+
:return: The resulting region coordinates in (x, z) order
|
|
75
|
+
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
def from_nibble_array(arr: ndarray) -> ndarray:
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
Unpacks a flat nibble array into a full size numpy array
|
|
82
|
+
|
|
83
|
+
:param arr: The nibble array
|
|
84
|
+
:return: The resulting array
|
|
85
|
+
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
def region_coords_to_chunk_coords(rx: int, rz: int) -> ChunkCoordinates:
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
Converts the supplied region coordinates into the minimum chunk coordinates of that region
|
|
92
|
+
|
|
93
|
+
:param rx: The x coordinate of the region
|
|
94
|
+
:param rz: The y coordinate of the region
|
|
95
|
+
:return: The resulting minimum chunk coordinates of that region in (x, z) order
|
|
96
|
+
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
def to_nibble_array(arr: ndarray) -> ndarray:
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
packs a full size numpy array into a nibble array.
|
|
103
|
+
|
|
104
|
+
:param arr: Full numpy array
|
|
105
|
+
:return: The nibble array
|
|
106
|
+
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
ChunkCoordinates: types.GenericAlias # value = tuple[int, int]
|
amulet/version.cpp
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#include <stdexcept>
|
|
2
|
+
#include <cstdint>
|
|
3
|
+
#include <compare>
|
|
4
|
+
|
|
5
|
+
#include <amulet/version.hpp>
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
namespace Amulet {
|
|
9
|
+
void VersionNumber::serialise(BinaryWriter& writer) const {
|
|
10
|
+
writer.writeNumeric<std::uint8_t>(1);
|
|
11
|
+
writer.writeNumeric<std::uint64_t>(vec.size());
|
|
12
|
+
for (const std::int64_t& v : vec){
|
|
13
|
+
writer.writeNumeric<std::int64_t>(v);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
std::shared_ptr<VersionNumber> VersionNumber::deserialise(BinaryReader& reader){
|
|
17
|
+
auto version_number = reader.readNumeric<std::uint8_t>();
|
|
18
|
+
switch (version_number) {
|
|
19
|
+
case 1:
|
|
20
|
+
{
|
|
21
|
+
std::uint64_t count;
|
|
22
|
+
reader.readNumericInto(count);
|
|
23
|
+
std::vector<std::int64_t> vec(count);
|
|
24
|
+
for (size_t i = 0; i < count; i++) {
|
|
25
|
+
reader.readNumericInto<std::int64_t>(vec[i]);
|
|
26
|
+
}
|
|
27
|
+
return std::make_shared<VersionNumber>(vec);
|
|
28
|
+
}
|
|
29
|
+
default:
|
|
30
|
+
throw std::invalid_argument("Unsupported version " + std::to_string(version_number));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
std::int64_t VersionNumber::operator[](size_t index) const {
|
|
35
|
+
if (index >= vec.size()) {
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
return vec[index];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
std::string VersionNumber::toString() const {
|
|
42
|
+
std::ostringstream oss;
|
|
43
|
+
for (size_t i = 0; i < vec.size(); ++i) {
|
|
44
|
+
if (i > 0){
|
|
45
|
+
oss << '.';
|
|
46
|
+
}
|
|
47
|
+
oss << vec[i];
|
|
48
|
+
}
|
|
49
|
+
return oss.str();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
std::vector<std::int64_t> VersionNumber::cropped_version() const {
|
|
53
|
+
bool found_non_zero = false;
|
|
54
|
+
std::vector<std::int64_t> out;
|
|
55
|
+
for (auto it = vec.rbegin(); it != vec.rend(); ++it) {
|
|
56
|
+
if (found_non_zero){
|
|
57
|
+
out.push_back(*it);
|
|
58
|
+
} else if (*it != 0) {
|
|
59
|
+
found_non_zero = true;
|
|
60
|
+
out.push_back(*it);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
std::reverse(out.begin(), out.end());
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
std::vector<std::int64_t> VersionNumber::padded_version(size_t len) const {
|
|
68
|
+
std::vector<std::int64_t> out(len);
|
|
69
|
+
for (size_t i = 0; i < len; i++){
|
|
70
|
+
out[i] = (*this)[i];
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
void PlatformVersionContainer::serialise(BinaryWriter& writer) const {
|
|
76
|
+
writer.writeNumeric<std::uint8_t>(1);
|
|
77
|
+
writer.writeSizeAndBytes(platform);
|
|
78
|
+
version->serialise(writer);
|
|
79
|
+
}
|
|
80
|
+
std::shared_ptr<PlatformVersionContainer> PlatformVersionContainer::deserialise(BinaryReader& reader){
|
|
81
|
+
auto version_number = reader.readNumeric<std::uint8_t>();
|
|
82
|
+
switch (version_number) {
|
|
83
|
+
case 1:
|
|
84
|
+
{
|
|
85
|
+
std::string platform = reader.readSizeAndBytes();
|
|
86
|
+
auto version = VersionNumber::deserialise(reader);
|
|
87
|
+
return std::make_shared<PlatformVersionContainer>(platform, version);
|
|
88
|
+
}
|
|
89
|
+
default:
|
|
90
|
+
throw std::invalid_argument("Unsupported version " + std::to_string(version_number));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
void VersionRange::serialise(BinaryWriter& writer) const {
|
|
95
|
+
writer.writeNumeric<std::uint8_t>(1);
|
|
96
|
+
writer.writeSizeAndBytes(platform);
|
|
97
|
+
min_version->serialise(writer);
|
|
98
|
+
max_version->serialise(writer);
|
|
99
|
+
}
|
|
100
|
+
std::shared_ptr<VersionRange> VersionRange::deserialise(BinaryReader& reader) {
|
|
101
|
+
auto version_number = reader.readNumeric<std::uint8_t>();
|
|
102
|
+
switch (version_number) {
|
|
103
|
+
case 1:
|
|
104
|
+
{
|
|
105
|
+
std::string platform = reader.readSizeAndBytes();
|
|
106
|
+
auto min_version = VersionNumber::deserialise(reader);
|
|
107
|
+
auto max_version = VersionNumber::deserialise(reader);
|
|
108
|
+
return std::make_shared<VersionRange>(platform, min_version, max_version);
|
|
109
|
+
}
|
|
110
|
+
default:
|
|
111
|
+
throw std::invalid_argument("Unsupported version " + std::to_string(version_number));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
bool VersionRange::contains(const PlatformType& platform_, const VersionNumber& version) const {
|
|
116
|
+
return platform == platform_ && *min_version <= version && version <= *max_version;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
void VersionRangeContainer::serialise(BinaryWriter& writer) const {
|
|
120
|
+
writer.writeNumeric<std::uint8_t>(1);
|
|
121
|
+
version_range->serialise(writer);
|
|
122
|
+
}
|
|
123
|
+
std::shared_ptr<VersionRangeContainer> VersionRangeContainer::deserialise(BinaryReader& reader) {
|
|
124
|
+
auto version_number = reader.readNumeric<std::uint8_t>();
|
|
125
|
+
switch (version_number) {
|
|
126
|
+
case 1:
|
|
127
|
+
{
|
|
128
|
+
return std::make_shared<VersionRangeContainer>(
|
|
129
|
+
VersionRange::deserialise(reader)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
default:
|
|
133
|
+
throw std::invalid_argument("Unsupported version " + std::to_string(version_number));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|