amulet-core 2.0a5__cp311-cp311-win_amd64.whl → 2.0a7__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/__init__.cp311-win_amd64.pyd +0 -0
- amulet/__init__.py.cpp +43 -0
- amulet/__init__.pyi +0 -2
- amulet/_init.py +0 -2
- amulet/_version.py +3 -3
- amulet/biome.py.cpp +122 -0
- amulet/biome.pyi +0 -2
- amulet/block.py.cpp +377 -0
- amulet/block.pyi +0 -2
- amulet/block_entity.py.cpp +115 -0
- amulet/block_entity.pyi +0 -2
- amulet/chunk.py.cpp +80 -0
- amulet/chunk.pyi +0 -2
- amulet/chunk_components/biome_3d_component.cpp +5 -0
- amulet/chunk_components/biome_3d_component.hpp +79 -0
- amulet/chunk_components/block_component.cpp +41 -0
- amulet/chunk_components/block_component.hpp +88 -0
- amulet/chunk_components/block_entity_component.cpp +5 -0
- amulet/chunk_components/block_entity_component.hpp +147 -0
- amulet/chunk_components/section_array_map.cpp +129 -0
- amulet/chunk_components/section_array_map.hpp +147 -0
- amulet/chunk_components.pyi +20 -18
- amulet/collections/eq.py.hpp +37 -0
- amulet/collections/hash.py.hpp +27 -0
- amulet/collections/holder.py.hpp +37 -0
- amulet/collections/iterator.py.hpp +80 -0
- amulet/collections/mapping.py.hpp +199 -0
- amulet/collections/mutable_mapping.py.hpp +226 -0
- amulet/collections/sequence.py.hpp +163 -0
- amulet/collections.pyi +8 -5
- amulet/entity.py +22 -20
- amulet/game/translate/_functions/_code_functions/_text.py +2 -2
- amulet/game/translate/_functions/abc.py +10 -3
- amulet/img/__init__.py +10 -0
- 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 +45 -0
- amulet/io/binary_writer.hpp +30 -0
- amulet/level/__init__.pyi +2 -6
- amulet/level/abc/_level/_creatable_level.py +1 -2
- amulet/level/abc/_level/_level.py +1 -5
- amulet/level/java/__init__.pyi +0 -5
- amulet/level/java/_raw/__init__.pyi +0 -4
- amulet/level/java/_raw/java_chunk_decode.cpp +531 -0
- amulet/level/java/_raw/java_chunk_decode.hpp +23 -0
- amulet/level/java/_raw/java_chunk_encode.cpp +25 -0
- amulet/level/java/_raw/java_chunk_encode.hpp +23 -0
- amulet/level/java/chunk_components/data_version_component.cpp +32 -0
- amulet/level/java/chunk_components/data_version_component.hpp +31 -0
- amulet/level/java/chunk_components/java_raw_chunk_component.cpp +56 -0
- amulet/level/java/chunk_components/java_raw_chunk_component.hpp +45 -0
- amulet/level/java/java_chunk.cpp +170 -0
- amulet/level/java/java_chunk.hpp +141 -0
- amulet/level/java/long_array.hpp +175 -0
- amulet/level/java/long_array.pyi +2 -1
- amulet/mesh/block/__init__.py +1 -0
- amulet/mesh/block/block_mesh.py +369 -0
- amulet/mesh/block/cube.py +149 -0
- amulet/mesh/block/missing_block.py +20 -0
- amulet/mesh/util.py +17 -0
- amulet/palette/biome_palette.hpp +85 -0
- amulet/palette/block_palette.cpp +32 -0
- amulet/palette/block_palette.hpp +93 -0
- amulet/player.py +4 -6
- amulet/pybind11/collections.hpp +118 -0
- amulet/pybind11/numpy.hpp +26 -0
- amulet/pybind11/py_module.hpp +34 -0
- amulet/pybind11/type_hints.hpp +51 -0
- amulet/pybind11/types.hpp +25 -0
- amulet/pybind11/typing.hpp +7 -0
- amulet/resource_pack/__init__.py +62 -0
- amulet/resource_pack/abc/__init__.py +2 -0
- amulet/resource_pack/abc/resource_pack.py +38 -0
- amulet/resource_pack/abc/resource_pack_manager.py +87 -0
- amulet/resource_pack/bedrock/__init__.py +2 -0
- 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 +31 -0
- amulet/resource_pack/bedrock/blockshapes/air.py +35 -0
- amulet/resource_pack/bedrock/blockshapes/base_blockshape.py +29 -0
- amulet/resource_pack/bedrock/blockshapes/bubble_column.py +29 -0
- amulet/resource_pack/bedrock/blockshapes/cake.py +46 -0
- amulet/resource_pack/bedrock/blockshapes/chest.py +54 -0
- amulet/resource_pack/bedrock/blockshapes/comparator.py +51 -0
- amulet/resource_pack/bedrock/blockshapes/cross_texture.py +186 -0
- amulet/resource_pack/bedrock/blockshapes/cross_texture0.py +17 -0
- amulet/resource_pack/bedrock/blockshapes/cross_texture_green.py +16 -0
- amulet/resource_pack/bedrock/blockshapes/cube.py +38 -0
- amulet/resource_pack/bedrock/blockshapes/default.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/door.py +38 -0
- amulet/resource_pack/bedrock/blockshapes/door1.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/door2.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/door3.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/door4.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/door5.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/door6.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/double_plant.py +40 -0
- amulet/resource_pack/bedrock/blockshapes/enchanting_table.py +22 -0
- amulet/resource_pack/bedrock/blockshapes/farmland.py +22 -0
- amulet/resource_pack/bedrock/blockshapes/fence.py +22 -0
- amulet/resource_pack/bedrock/blockshapes/flat.py +55 -0
- amulet/resource_pack/bedrock/blockshapes/flat_wall.py +55 -0
- amulet/resource_pack/bedrock/blockshapes/furnace.py +44 -0
- amulet/resource_pack/bedrock/blockshapes/furnace_lit.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/green_cube.py +39 -0
- amulet/resource_pack/bedrock/blockshapes/ladder.py +36 -0
- amulet/resource_pack/bedrock/blockshapes/lilypad.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/partial_block.py +57 -0
- amulet/resource_pack/bedrock/blockshapes/piston.py +44 -0
- amulet/resource_pack/bedrock/blockshapes/piston_arm.py +72 -0
- amulet/resource_pack/bedrock/blockshapes/portal_frame.py +22 -0
- amulet/resource_pack/bedrock/blockshapes/pressure_plate.py +29 -0
- amulet/resource_pack/bedrock/blockshapes/pumpkin.py +36 -0
- amulet/resource_pack/bedrock/blockshapes/pumpkin_carved.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/pumpkin_lit.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/red_dust.py +14 -0
- amulet/resource_pack/bedrock/blockshapes/repeater.py +53 -0
- amulet/resource_pack/bedrock/blockshapes/slab.py +33 -0
- amulet/resource_pack/bedrock/blockshapes/slab_double.py +15 -0
- amulet/resource_pack/bedrock/blockshapes/tree.py +41 -0
- amulet/resource_pack/bedrock/blockshapes/turtle_egg.py +15 -0
- amulet/resource_pack/bedrock/blockshapes/vine.py +52 -0
- amulet/resource_pack/bedrock/blockshapes/wall.py +22 -0
- amulet/resource_pack/bedrock/blockshapes/water.py +38 -0
- amulet/resource_pack/bedrock/download_resources.py +147 -0
- amulet/resource_pack/bedrock/resource_pack.py +40 -0
- amulet/resource_pack/bedrock/resource_pack_manager.py +361 -0
- amulet/resource_pack/bedrock/sort_blockshapes.py +15 -0
- amulet/resource_pack/java/__init__.py +2 -0
- amulet/resource_pack/java/download_resources.py +212 -0
- 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 +44 -0
- amulet/resource_pack/java/resource_pack_manager.py +551 -0
- amulet/resource_pack/unknown_resource_pack.py +10 -0
- amulet/utils/__init__.pyi +0 -5
- amulet/utils/call_spec/_call_spec.py +2 -7
- amulet/utils/comment_json.py +188 -0
- amulet/utils/matrix.py +3 -3
- amulet/utils/numpy.hpp +36 -0
- amulet/utils/numpy_helpers.py +2 -2
- amulet/utils/world_utils.py +2 -2
- amulet/version.py.cpp +281 -0
- amulet/version.pyi +0 -8
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a7.dist-info}/METADATA +3 -3
- amulet_core-2.0a7.dist-info/RECORD +295 -0
- amulet/chunk_/components/biome.py +0 -155
- amulet/chunk_/components/block_entity.py +0 -117
- amulet/chunk_/components/entity.py +0 -64
- amulet/chunk_/components/height_2d.py +0 -16
- amulet/level/bedrock/__init__.py +0 -2
- amulet/level/bedrock/_chunk_handle.py +0 -19
- amulet/level/bedrock/_dimension.py +0 -22
- amulet/level/bedrock/_level.py +0 -187
- amulet/level/bedrock/_raw/__init__.py +0 -5
- amulet/level/bedrock/_raw/_actor_counter.py +0 -53
- amulet/level/bedrock/_raw/_chunk.py +0 -54
- amulet/level/bedrock/_raw/_chunk_decode.py +0 -668
- amulet/level/bedrock/_raw/_chunk_encode.py +0 -602
- amulet/level/bedrock/_raw/_constant.py +0 -9
- amulet/level/bedrock/_raw/_dimension.py +0 -343
- amulet/level/bedrock/_raw/_level.py +0 -463
- amulet/level/bedrock/_raw/_level_dat.py +0 -90
- amulet/level/bedrock/_raw/_typing.py +0 -6
- amulet/level/bedrock/_raw/leveldb_chunk_versions.py +0 -83
- amulet/level/bedrock/chunk/__init__.py +0 -1
- amulet/level/bedrock/chunk/_chunk.py +0 -126
- amulet/level/bedrock/chunk/components/chunk_version.py +0 -12
- amulet/level/bedrock/chunk/components/finalised_state.py +0 -13
- amulet/level/bedrock/chunk/components/raw_chunk.py +0 -15
- amulet/level/construction/__init__.py +0 -0
- amulet/level/java/_chunk_handle.pyi +0 -15
- amulet/level/java/_dimension.pyi +0 -13
- amulet/level/java/_level.pyi +0 -120
- amulet/level/java/_raw/_chunk_decode.py +0 -561
- amulet/level/java/_raw/_chunk_encode.py +0 -463
- amulet/level/java/_raw/_constant.pyi +0 -20
- amulet/level/java/_raw/_data_pack/__init__.pyi +0 -8
- amulet/level/java/_raw/_data_pack/data_pack.pyi +0 -197
- amulet/level/java/_raw/_data_pack/data_pack_manager.pyi +0 -75
- amulet/level/java/_raw/_dimension.pyi +0 -72
- amulet/level/java/_raw/_level.pyi +0 -238
- amulet/level/java/_raw/_typing.pyi +0 -5
- amulet/level/java/anvil/__init__.pyi +0 -11
- amulet/level/java/anvil/_dimension.pyi +0 -109
- amulet/level/java/anvil/_region.pyi +0 -197
- amulet/level/java/anvil/_sector_manager.pyi +0 -142
- 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/utils/call_spec/__init__.pyi +0 -53
- amulet/utils/call_spec/_call_spec.pyi +0 -272
- amulet/utils/matrix.pyi +0 -177
- amulet/utils/shareable_lock.pyi +0 -190
- amulet/utils/signal/__init__.pyi +0 -25
- amulet/utils/signal/_signal.pyi +0 -84
- amulet/utils/task_manager.pyi +0 -168
- amulet/utils/typing.py +0 -4
- amulet/utils/typing.pyi +0 -6
- amulet/utils/weakref.pyi +0 -50
- amulet/utils/world_utils.pyi +0 -109
- amulet_core-2.0a5.dist-info/RECORD +0 -210
- /amulet/{level/bedrock/chunk/components → mesh}/__init__.py +0 -0
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a7.dist-info}/WHEEL +0 -0
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a7.dist-info}/entry_points.txt +0 -0
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a7.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
from json import JSONDecodeError, loads as json_loads
|
|
2
|
+
from typing import TextIO, Union
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Some of the Bedrock json files contain comments which is not valid JSON and the standard json parser
|
|
6
|
+
will throw errors. This will first try and use the vanilla json parser and fall back to the slower version if that fails.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
JSONValue = Union[str, int, float, bool, None, "JSONDict", "JSONList"]
|
|
11
|
+
JSONDict = dict[str, JSONValue]
|
|
12
|
+
JSONList = list[JSONValue]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CommentJSONDecodeError(JSONDecodeError):
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def from_file(path: str) -> JSONValue:
|
|
20
|
+
with open(path) as f:
|
|
21
|
+
return load(f)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def load(obj: TextIO) -> JSONValue:
|
|
25
|
+
return loads(obj.read())
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def loads(s: str) -> JSONValue:
|
|
29
|
+
try:
|
|
30
|
+
return json_loads(s) # type: ignore
|
|
31
|
+
except JSONDecodeError:
|
|
32
|
+
return _loads(s)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _loads(text: str) -> JSONValue:
|
|
36
|
+
# given a valid MinecraftJSON string will return the values as python objects
|
|
37
|
+
# in this context MinecraftJSON is standard JSON but with comment blocks and
|
|
38
|
+
# line comments that would normally be illegal in standard JSON
|
|
39
|
+
_number = set("0123456789-")
|
|
40
|
+
_float = set("0123456789-.")
|
|
41
|
+
_whitespace = set(" \t\r\n")
|
|
42
|
+
|
|
43
|
+
def strip_whitespace(index: int) -> int:
|
|
44
|
+
# skips whitespace characters (<space>, <tab>, <charrage return> and <newline>)
|
|
45
|
+
# as well as block comments and line comments
|
|
46
|
+
while text[index] in _whitespace:
|
|
47
|
+
index += 1
|
|
48
|
+
if text[index] == "/":
|
|
49
|
+
if text[index + 1] == "/":
|
|
50
|
+
index += 2
|
|
51
|
+
while text[index] != "\n":
|
|
52
|
+
index += 1
|
|
53
|
+
index = strip_whitespace(index)
|
|
54
|
+
elif text[index + 1] == "*":
|
|
55
|
+
index += 2
|
|
56
|
+
while text[index : index + 2] != "*/":
|
|
57
|
+
index += 1
|
|
58
|
+
if index + 1 >= len(text):
|
|
59
|
+
raise JSONDecodeError(
|
|
60
|
+
"expected */ but reached the end of file", text, index
|
|
61
|
+
)
|
|
62
|
+
index += 2
|
|
63
|
+
index = strip_whitespace(index)
|
|
64
|
+
else:
|
|
65
|
+
raise JSONDecodeError(f"unexpected / at index {index}", text, index)
|
|
66
|
+
return index
|
|
67
|
+
|
|
68
|
+
def parse_json_recursive(index: int = 0) -> tuple[JSONValue, int]:
|
|
69
|
+
index = strip_whitespace(index)
|
|
70
|
+
if text[index] == "{":
|
|
71
|
+
index += 1
|
|
72
|
+
# dictionary
|
|
73
|
+
json_obj = {}
|
|
74
|
+
repeat = True
|
|
75
|
+
while repeat:
|
|
76
|
+
index = strip_whitespace(index)
|
|
77
|
+
# }"
|
|
78
|
+
if text[index] == '"':
|
|
79
|
+
index += 1
|
|
80
|
+
key = ""
|
|
81
|
+
while text[index] != '"':
|
|
82
|
+
key += text[index]
|
|
83
|
+
index += 1
|
|
84
|
+
index += 1
|
|
85
|
+
|
|
86
|
+
index = strip_whitespace(index)
|
|
87
|
+
|
|
88
|
+
if text[index] == ":":
|
|
89
|
+
index += 1
|
|
90
|
+
else:
|
|
91
|
+
raise JSONDecodeError(
|
|
92
|
+
f"expected : got {text[index]} at index {index}",
|
|
93
|
+
text,
|
|
94
|
+
index,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
index = strip_whitespace(index)
|
|
98
|
+
|
|
99
|
+
json_obj[key], index = parse_json_recursive(index)
|
|
100
|
+
|
|
101
|
+
index = strip_whitespace(index)
|
|
102
|
+
|
|
103
|
+
if text[index] == ",":
|
|
104
|
+
index += 1
|
|
105
|
+
else:
|
|
106
|
+
repeat = False
|
|
107
|
+
else:
|
|
108
|
+
repeat = False
|
|
109
|
+
|
|
110
|
+
if index >= len(text):
|
|
111
|
+
raise JSONDecodeError("expected } but reached end of file", text, index)
|
|
112
|
+
elif text[index] == "}":
|
|
113
|
+
index += 1
|
|
114
|
+
else:
|
|
115
|
+
raise JSONDecodeError(
|
|
116
|
+
f"expected }} got {text[index]} at index {index}", text, index
|
|
117
|
+
)
|
|
118
|
+
return json_obj, index
|
|
119
|
+
|
|
120
|
+
elif text[index] == "[":
|
|
121
|
+
index += 1
|
|
122
|
+
# list
|
|
123
|
+
json_array = []
|
|
124
|
+
index = strip_whitespace(index)
|
|
125
|
+
repeat = text[index] != "]"
|
|
126
|
+
while repeat:
|
|
127
|
+
val, index = parse_json_recursive(index)
|
|
128
|
+
json_array.append(val)
|
|
129
|
+
|
|
130
|
+
index = strip_whitespace(index)
|
|
131
|
+
|
|
132
|
+
if text[index] == ",":
|
|
133
|
+
index += 1
|
|
134
|
+
else:
|
|
135
|
+
repeat = False
|
|
136
|
+
index = strip_whitespace(index)
|
|
137
|
+
|
|
138
|
+
if index >= len(text):
|
|
139
|
+
raise JSONDecodeError("expected ] but reached end of file", text, index)
|
|
140
|
+
elif text[index] == "]":
|
|
141
|
+
index += 1
|
|
142
|
+
else:
|
|
143
|
+
raise JSONDecodeError(
|
|
144
|
+
f"expected ] got {text[index]} at index {index}", text, index
|
|
145
|
+
)
|
|
146
|
+
return json_array, index
|
|
147
|
+
|
|
148
|
+
elif text[index] == '"':
|
|
149
|
+
index += 1
|
|
150
|
+
# string
|
|
151
|
+
json_obj_list = []
|
|
152
|
+
while text[index] != '"':
|
|
153
|
+
json_obj_list.append(text[index])
|
|
154
|
+
index += 1
|
|
155
|
+
index += 1
|
|
156
|
+
return "".join(json_obj_list), index
|
|
157
|
+
|
|
158
|
+
elif text[index] in _number:
|
|
159
|
+
# number
|
|
160
|
+
json_obj_list = []
|
|
161
|
+
while text[index] in _float:
|
|
162
|
+
json_obj_list += text[index]
|
|
163
|
+
index += 1
|
|
164
|
+
if "." in json_obj_list:
|
|
165
|
+
return float("".join(json_obj_list)), index
|
|
166
|
+
else:
|
|
167
|
+
return int("".join(json_obj_list)), index
|
|
168
|
+
|
|
169
|
+
elif text[index] == "n" and text[index : index + 4] == "null":
|
|
170
|
+
index += 4
|
|
171
|
+
return None, index
|
|
172
|
+
|
|
173
|
+
elif text[index] == "t" and text[index : index + 4] == "true":
|
|
174
|
+
index += 4
|
|
175
|
+
return True, index
|
|
176
|
+
|
|
177
|
+
elif text[index] == "f" and text[index : index + 5] == "false":
|
|
178
|
+
index += 5
|
|
179
|
+
return False, index
|
|
180
|
+
else:
|
|
181
|
+
raise JSONDecodeError(
|
|
182
|
+
f'unexpected key {text[index]} at {index}. Expected {{, [, ", num, null, true or false',
|
|
183
|
+
text,
|
|
184
|
+
index,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# call recursive function and pass back python object
|
|
188
|
+
return parse_json_recursive()[0]
|
amulet/utils/matrix.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Literal
|
|
2
2
|
import math
|
|
3
3
|
import numpy
|
|
4
4
|
from amulet.data_types import FloatTriplet, PointCoordinates
|
|
@@ -193,8 +193,8 @@ def inverse_transform_matrix(
|
|
|
193
193
|
|
|
194
194
|
def decompose_transformation_matrix(
|
|
195
195
|
matrix: numpy.ndarray,
|
|
196
|
-
) ->
|
|
197
|
-
|
|
196
|
+
) -> tuple[
|
|
197
|
+
tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]
|
|
198
198
|
]:
|
|
199
199
|
"""
|
|
200
200
|
Decompose a 4x4 transformation matrix into scale, rotation and displacement tuples.
|
amulet/utils/numpy.hpp
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <cstdint>
|
|
4
|
+
#include <vector>
|
|
5
|
+
#include <utility>
|
|
6
|
+
#include <span>
|
|
7
|
+
#include <unordered_map>
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
namespace Amulet {
|
|
11
|
+
// dtypeT can be any numerical type.
|
|
12
|
+
// inverseT must be large enough to store the length of arr.
|
|
13
|
+
template <typename dtypeT, typename inverseT>
|
|
14
|
+
void unique_inverse(const std::span<dtypeT> arr, std::vector<dtypeT>& unique, std::span<inverseT>& inverse){
|
|
15
|
+
if (arr.size() != inverse.size()){
|
|
16
|
+
throw std::invalid_argument("arr and inverse must have the same size.");
|
|
17
|
+
}
|
|
18
|
+
if (unique.size()){
|
|
19
|
+
throw std::invalid_argument("unique must be empty.");
|
|
20
|
+
}
|
|
21
|
+
// Map from found values to their index in unique
|
|
22
|
+
std::unordered_map<dtypeT, inverseT> value_to_index;
|
|
23
|
+
|
|
24
|
+
for (inverseT i = 0; i < arr.size(); i++){
|
|
25
|
+
dtypeT value = arr[i];
|
|
26
|
+
auto it = value_to_index.find(value);
|
|
27
|
+
if (it == value_to_index.end()){
|
|
28
|
+
inverse[i] = unique.size();
|
|
29
|
+
value_to_index[value] = unique.size();
|
|
30
|
+
unique.push_back(value);
|
|
31
|
+
} else {
|
|
32
|
+
inverse[i] = it->second;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
amulet/utils/numpy_helpers.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import TypeVar
|
|
2
2
|
from collections.abc import Collection
|
|
3
3
|
import numpy
|
|
4
4
|
|
|
5
5
|
T = TypeVar("T")
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def brute_sort_objects_no_hash(data: Collection[T]) ->
|
|
8
|
+
def brute_sort_objects_no_hash(data: Collection[T]) -> tuple[list[T], numpy.ndarray]:
|
|
9
9
|
unique: list[T] = []
|
|
10
10
|
inverse = numpy.zeros(dtype=numpy.uint32, shape=len(data))
|
|
11
11
|
for i, d in enumerate(data):
|
amulet/utils/world_utils.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import math
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Optional
|
|
5
5
|
import numpy
|
|
6
6
|
from numpy import ndarray, zeros, uint8
|
|
7
7
|
from amulet.data_types import ChunkCoordinates
|
|
@@ -9,7 +9,7 @@ from amulet.data_types import ChunkCoordinates
|
|
|
9
9
|
|
|
10
10
|
def block_coords_to_chunk_coords(
|
|
11
11
|
*args: int, sub_chunk_size: int = 16
|
|
12
|
-
) ->
|
|
12
|
+
) -> tuple[int, ...]:
|
|
13
13
|
"""
|
|
14
14
|
Converts the supplied block coordinates into chunk coordinates
|
|
15
15
|
|
amulet/version.py.cpp
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
#include <sstream>
|
|
2
|
+
|
|
3
|
+
#include <pybind11/pybind11.h>
|
|
4
|
+
#include <pybind11/stl.h>
|
|
5
|
+
#include <pybind11/operators.h>
|
|
6
|
+
|
|
7
|
+
#include <amulet/collections/eq.py.hpp>
|
|
8
|
+
#include <amulet/version.hpp>
|
|
9
|
+
|
|
10
|
+
namespace py = pybind11;
|
|
11
|
+
|
|
12
|
+
void init_version(py::module m_parent) {
|
|
13
|
+
auto m = m_parent.def_submodule("version");
|
|
14
|
+
py::options options;
|
|
15
|
+
|
|
16
|
+
m.attr("PlatformType") = py::module::import("builtins").attr("str");
|
|
17
|
+
|
|
18
|
+
py::class_<Amulet::VersionNumber, std::shared_ptr<Amulet::VersionNumber>> VersionNumber(m, "VersionNumber",
|
|
19
|
+
"This class is designed to store semantic versions and data versions and allow comparisons between them.\n"
|
|
20
|
+
"\n"
|
|
21
|
+
">>> v1 = VersionNumber(1, 0, 0)\n"
|
|
22
|
+
">>> v2 = VersionNumber(1, 0)\n"
|
|
23
|
+
">>> assert v2 == v1\n"
|
|
24
|
+
"\n"
|
|
25
|
+
"This class should also be used to store single number data versions.\n"
|
|
26
|
+
">>> v3 = VersionNumber(3578)"
|
|
27
|
+
);
|
|
28
|
+
options.disable_function_signatures();
|
|
29
|
+
VersionNumber.def(
|
|
30
|
+
py::init(
|
|
31
|
+
[](py::args v){
|
|
32
|
+
return std::make_shared<Amulet::VersionNumber>(
|
|
33
|
+
v.cast<std::vector<std::int64_t>>()
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
),
|
|
37
|
+
py::doc("__init__(self: amulet.version.VersionNumber, *args: typing.SupportsInt) -> None")
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Start collections.abc.Sequence
|
|
41
|
+
VersionNumber.def(
|
|
42
|
+
"__getitem__",
|
|
43
|
+
&Amulet::VersionNumber::operator[],
|
|
44
|
+
py::doc(
|
|
45
|
+
"__getitem__(*args, **kwargs)\n"
|
|
46
|
+
"Overloaded function.\n"
|
|
47
|
+
"1. __getitem__(self: amulet.version.VersionNumber, item: typing.SupportsInt) -> int\n"
|
|
48
|
+
"2. __getitem__(self: amulet.version.VersionNumber, item: slice) -> list[int]"
|
|
49
|
+
)
|
|
50
|
+
);
|
|
51
|
+
VersionNumber.def(
|
|
52
|
+
"__getitem__",
|
|
53
|
+
[](const Amulet::VersionNumber& self, const py::slice &slice) -> std::vector<std::int64_t> {
|
|
54
|
+
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
|
55
|
+
if (!slice.compute(self.size(), &start, &stop, &step, &slicelength)) {
|
|
56
|
+
throw py::error_already_set();
|
|
57
|
+
}
|
|
58
|
+
std::vector<std::int64_t> out(slicelength);
|
|
59
|
+
for (size_t i = 0; i < slicelength; ++i) {
|
|
60
|
+
out[i] = self[start];
|
|
61
|
+
start += step;
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
options.enable_function_signatures();
|
|
67
|
+
|
|
68
|
+
VersionNumber.def(
|
|
69
|
+
"__repr__",
|
|
70
|
+
[](const Amulet::VersionNumber& self){
|
|
71
|
+
std::ostringstream oss;
|
|
72
|
+
auto& vec = self.get_vector();
|
|
73
|
+
oss << "VersionNumber(";
|
|
74
|
+
for (size_t i = 0; i < vec.size(); i++){
|
|
75
|
+
if (i != 0){
|
|
76
|
+
oss << ", ";
|
|
77
|
+
}
|
|
78
|
+
oss << vec[i];
|
|
79
|
+
}
|
|
80
|
+
oss << ")";
|
|
81
|
+
return oss.str();
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
VersionNumber.def(
|
|
85
|
+
py::pickle(
|
|
86
|
+
[](const Amulet::VersionNumber& self) {
|
|
87
|
+
return py::bytes(Amulet::serialise(self));
|
|
88
|
+
},
|
|
89
|
+
[](py::bytes state){
|
|
90
|
+
return Amulet::deserialise<Amulet::VersionNumber>(state.cast<std::string>());
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
VersionNumber.def(
|
|
96
|
+
"__len__",
|
|
97
|
+
&Amulet::VersionNumber::size
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
VersionNumber.def(
|
|
101
|
+
"__contains__",
|
|
102
|
+
[](const Amulet::VersionNumber& self, std::int64_t value) {
|
|
103
|
+
for (auto it = self.begin(); it != self.end(); it++){
|
|
104
|
+
if (*it == value) return true;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
VersionNumber.def(
|
|
111
|
+
"__iter__",
|
|
112
|
+
[](const Amulet::VersionNumber& self) {return py::make_iterator(self.begin(), self.end());},
|
|
113
|
+
py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
VersionNumber.def(
|
|
117
|
+
"__reversed__",
|
|
118
|
+
[](const Amulet::VersionNumber& self) {return py::make_iterator(self.rbegin(), self.rend());},
|
|
119
|
+
py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
VersionNumber.def(
|
|
123
|
+
"index",
|
|
124
|
+
[](const Amulet::VersionNumber& self, std::int64_t value, size_t start, size_t stop) {
|
|
125
|
+
start = std::min(start, self.size());
|
|
126
|
+
stop = std::min(stop, self.size());
|
|
127
|
+
for (size_t i = start; i < stop; i++){
|
|
128
|
+
if (self[i] == value) return i;
|
|
129
|
+
}
|
|
130
|
+
throw py::value_error(std::to_string(value) + " is not in VersionNumber.");
|
|
131
|
+
},
|
|
132
|
+
py::arg("value"), py::arg("start") = 0, py::arg("stop") = std::numeric_limits<size_t>::max()
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
VersionNumber.def(
|
|
136
|
+
"count",
|
|
137
|
+
[](const Amulet::VersionNumber& self, std::int64_t value) {
|
|
138
|
+
size_t count = 0;
|
|
139
|
+
for (size_t i = 0; i < self.size(); i++){
|
|
140
|
+
if (self[i] == value) ++count;
|
|
141
|
+
}
|
|
142
|
+
return count;
|
|
143
|
+
},
|
|
144
|
+
py::arg("value")
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
// End collections.abc.Sequence
|
|
148
|
+
|
|
149
|
+
VersionNumber.def(
|
|
150
|
+
"__str__",
|
|
151
|
+
&Amulet::VersionNumber::toString
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
Eq(VersionNumber);
|
|
155
|
+
Eq_default(VersionNumber);
|
|
156
|
+
VersionNumber.def(pybind11::self < pybind11::self);
|
|
157
|
+
VersionNumber.def(pybind11::self > pybind11::self);
|
|
158
|
+
VersionNumber.def(pybind11::self <= pybind11::self);
|
|
159
|
+
VersionNumber.def(pybind11::self >= pybind11::self);
|
|
160
|
+
|
|
161
|
+
VersionNumber.def(
|
|
162
|
+
"cropped_version",
|
|
163
|
+
[](const Amulet::VersionNumber& self) -> py::tuple {return py::cast(self.cropped_version());},
|
|
164
|
+
py::doc("The version number with trailing zeros cut off.")
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
VersionNumber.def(
|
|
168
|
+
"padded_version",
|
|
169
|
+
[](const Amulet::VersionNumber& self, size_t len) -> py::tuple {return py::cast(self.padded_version(len));},
|
|
170
|
+
py::doc("Get the version number padded with zeros to the given length."),
|
|
171
|
+
py::arg("len")
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
VersionNumber.def(
|
|
175
|
+
"__hash__",
|
|
176
|
+
[](const Amulet::VersionNumber& self) {
|
|
177
|
+
py::tuple py_tuple = py::cast(self.cropped_version());
|
|
178
|
+
return py::hash(py_tuple);
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
py::module::import("collections.abc").attr("Sequence").attr("register")(VersionNumber);
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
py::class_<Amulet::PlatformVersionContainer, std::shared_ptr<Amulet::PlatformVersionContainer>> PlatformVersionContainer(m, "PlatformVersionContainer");
|
|
186
|
+
PlatformVersionContainer.def(
|
|
187
|
+
py::init<
|
|
188
|
+
const Amulet::PlatformType&,
|
|
189
|
+
std::shared_ptr<Amulet::VersionNumber>
|
|
190
|
+
>(),
|
|
191
|
+
py::arg("platform"),
|
|
192
|
+
py::arg("version")
|
|
193
|
+
);
|
|
194
|
+
PlatformVersionContainer.def_property_readonly("platform", &Amulet::PlatformVersionContainer::get_platform);
|
|
195
|
+
PlatformVersionContainer.def_property_readonly("version", &Amulet::PlatformVersionContainer::get_version);
|
|
196
|
+
PlatformVersionContainer.def(
|
|
197
|
+
"__repr__",
|
|
198
|
+
[](const Amulet::PlatformVersionContainer& self){
|
|
199
|
+
return "PlatformVersionContainer(" +
|
|
200
|
+
py::repr(py::cast(self.get_platform())).cast<std::string>() + ", " +
|
|
201
|
+
py::repr(py::cast(self.get_version())).cast<std::string>() +
|
|
202
|
+
")";
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
PlatformVersionContainer.def(
|
|
206
|
+
py::pickle(
|
|
207
|
+
[](const Amulet::PlatformVersionContainer& self) -> py::bytes {
|
|
208
|
+
return py::bytes(Amulet::serialise(self));
|
|
209
|
+
},
|
|
210
|
+
[](py::bytes state){
|
|
211
|
+
return Amulet::deserialise<Amulet::PlatformVersionContainer>(state.cast<std::string>());
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
py::class_<Amulet::VersionRange, std::shared_ptr<Amulet::VersionRange>> VersionRange(m, "VersionRange");
|
|
218
|
+
VersionRange.def(
|
|
219
|
+
py::init<
|
|
220
|
+
const Amulet::PlatformType&,
|
|
221
|
+
std::shared_ptr<Amulet::VersionNumber>,
|
|
222
|
+
std::shared_ptr<Amulet::VersionNumber>
|
|
223
|
+
>(),
|
|
224
|
+
py::arg("platform"),
|
|
225
|
+
py::arg("min_version"),
|
|
226
|
+
py::arg("max_version")
|
|
227
|
+
);
|
|
228
|
+
VersionRange.def_property_readonly("platform", &Amulet::VersionRange::get_platform);
|
|
229
|
+
VersionRange.def_property_readonly("min_version", &Amulet::VersionRange::get_min_version);
|
|
230
|
+
VersionRange.def_property_readonly("max_version", &Amulet::VersionRange::get_max_version);
|
|
231
|
+
VersionRange.def(
|
|
232
|
+
"contains",
|
|
233
|
+
&Amulet::VersionRange::contains
|
|
234
|
+
);
|
|
235
|
+
VersionRange.def(
|
|
236
|
+
"__repr__",
|
|
237
|
+
[](const Amulet::VersionRange& self){
|
|
238
|
+
return "VersionRange(" +
|
|
239
|
+
py::repr(py::cast(self.get_platform())).cast<std::string>() + ", " +
|
|
240
|
+
py::repr(py::cast(self.get_min_version())).cast<std::string>() + ", " +
|
|
241
|
+
py::repr(py::cast(self.get_max_version())).cast<std::string>() +
|
|
242
|
+
")";
|
|
243
|
+
}
|
|
244
|
+
);
|
|
245
|
+
VersionRange.def(
|
|
246
|
+
py::pickle(
|
|
247
|
+
[](const Amulet::VersionRange& self) -> py::bytes {
|
|
248
|
+
return py::bytes(Amulet::serialise(self));
|
|
249
|
+
},
|
|
250
|
+
[](py::bytes state){
|
|
251
|
+
return Amulet::deserialise<Amulet::VersionRange>(state.cast<std::string>());
|
|
252
|
+
}
|
|
253
|
+
)
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
py::class_<Amulet::VersionRangeContainer, std::shared_ptr<Amulet::VersionRangeContainer>> VersionRangeContainer(m, "VersionRangeContainer");
|
|
258
|
+
VersionRangeContainer.def(
|
|
259
|
+
py::init<
|
|
260
|
+
std::shared_ptr<Amulet::VersionRange>
|
|
261
|
+
>(),
|
|
262
|
+
py::arg("version_range")
|
|
263
|
+
);
|
|
264
|
+
VersionRangeContainer.def_property_readonly("version_range", &Amulet::VersionRangeContainer::get_version_range);
|
|
265
|
+
VersionRangeContainer.def(
|
|
266
|
+
"__repr__",
|
|
267
|
+
[](const Amulet::VersionRangeContainer& self){
|
|
268
|
+
return "VersionRangeContainer(" + py::repr(py::cast(self.get_version_range())).cast<std::string>() + ")";
|
|
269
|
+
}
|
|
270
|
+
);
|
|
271
|
+
VersionRangeContainer.def(
|
|
272
|
+
py::pickle(
|
|
273
|
+
[](const Amulet::VersionRangeContainer& self) -> py::bytes {
|
|
274
|
+
return py::bytes(Amulet::serialise(self));
|
|
275
|
+
},
|
|
276
|
+
[](py::bytes state){
|
|
277
|
+
return Amulet::deserialise<Amulet::VersionRangeContainer>(state.cast<std::string>());
|
|
278
|
+
}
|
|
279
|
+
)
|
|
280
|
+
);
|
|
281
|
+
}
|
amulet/version.pyi
CHANGED
|
@@ -13,10 +13,8 @@ __all__ = [
|
|
|
13
13
|
]
|
|
14
14
|
|
|
15
15
|
class PlatformVersionContainer:
|
|
16
|
-
def __getstate__(self) -> bytes: ...
|
|
17
16
|
def __init__(self, platform: str, version: VersionNumber) -> None: ...
|
|
18
17
|
def __repr__(self) -> str: ...
|
|
19
|
-
def __setstate__(self, arg0: bytes) -> None: ...
|
|
20
18
|
@property
|
|
21
19
|
def platform(self) -> str: ...
|
|
22
20
|
@property
|
|
@@ -44,7 +42,6 @@ class VersionNumber:
|
|
|
44
42
|
def __getitem__(self, item: typing.SupportsInt) -> int: ...
|
|
45
43
|
@typing.overload
|
|
46
44
|
def __getitem__(self, item: slice) -> list[int]: ...
|
|
47
|
-
def __getstate__(self) -> bytes: ...
|
|
48
45
|
def __gt__(self, arg0: VersionNumber) -> bool: ...
|
|
49
46
|
def __hash__(self) -> int: ...
|
|
50
47
|
def __init__(self, *args: typing.SupportsInt) -> None: ...
|
|
@@ -54,7 +51,6 @@ class VersionNumber:
|
|
|
54
51
|
def __lt__(self, arg0: VersionNumber) -> bool: ...
|
|
55
52
|
def __repr__(self) -> str: ...
|
|
56
53
|
def __reversed__(self) -> typing.Iterator[int]: ...
|
|
57
|
-
def __setstate__(self, arg0: bytes) -> None: ...
|
|
58
54
|
def __str__(self) -> str: ...
|
|
59
55
|
def count(self, value: int) -> int: ...
|
|
60
56
|
def cropped_version(self) -> tuple:
|
|
@@ -71,12 +67,10 @@ class VersionNumber:
|
|
|
71
67
|
"""
|
|
72
68
|
|
|
73
69
|
class VersionRange:
|
|
74
|
-
def __getstate__(self) -> bytes: ...
|
|
75
70
|
def __init__(
|
|
76
71
|
self, platform: str, min_version: VersionNumber, max_version: VersionNumber
|
|
77
72
|
) -> None: ...
|
|
78
73
|
def __repr__(self) -> str: ...
|
|
79
|
-
def __setstate__(self, arg0: bytes) -> None: ...
|
|
80
74
|
def contains(self, arg0: str, arg1: VersionNumber) -> bool: ...
|
|
81
75
|
@property
|
|
82
76
|
def max_version(self) -> VersionNumber: ...
|
|
@@ -86,9 +80,7 @@ class VersionRange:
|
|
|
86
80
|
def platform(self) -> str: ...
|
|
87
81
|
|
|
88
82
|
class VersionRangeContainer:
|
|
89
|
-
def __getstate__(self) -> bytes: ...
|
|
90
83
|
def __init__(self, version_range: VersionRange) -> None: ...
|
|
91
84
|
def __repr__(self) -> str: ...
|
|
92
|
-
def __setstate__(self, arg0: bytes) -> None: ...
|
|
93
85
|
@property
|
|
94
86
|
def version_range(self) -> VersionRange: ...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: amulet-core
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.0a7
|
|
4
4
|
Summary: A Python library for reading/writing Minecraft's various save formats.
|
|
5
5
|
Home-page: https://www.amuletmc.com
|
|
6
6
|
Author: James Clare, Ben Gothard et al.
|
|
@@ -10,8 +10,8 @@ Classifier: Programming Language :: Python :: 3
|
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
11
|
Requires-Python: >=3.11
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
|
-
Requires-Dist: numpy~=
|
|
14
|
-
Requires-Dist: amulet-nbt~=4.
|
|
13
|
+
Requires-Dist: numpy~=2.0
|
|
14
|
+
Requires-Dist: amulet-nbt~=4.0a3
|
|
15
15
|
Requires-Dist: portalocker~=2.4
|
|
16
16
|
Requires-Dist: amulet-leveldb~=1.0b0
|
|
17
17
|
Requires-Dist: platformdirs~=3.1
|