amulet-core 2.0.7a0__cp312-cp312-macosx_10_15_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.
Files changed (53) hide show
  1. amulet/core/__init__.py +38 -0
  2. amulet/core/__init__.pyi +31 -0
  3. amulet/core/__pyinstaller/__init__.py +2 -0
  4. amulet/core/__pyinstaller/hook-amulet.core.py +4 -0
  5. amulet/core/_amulet_core.cpython-312-darwin.so +0 -0
  6. amulet/core/_amulet_core.pyi +7 -0
  7. amulet/core/_version.py +21 -0
  8. amulet/core/amulet_coreConfig.cmake +23 -0
  9. amulet/core/biome/__init__.pyi +75 -0
  10. amulet/core/biome/biome.hpp +53 -0
  11. amulet/core/block/__init__.pyi +273 -0
  12. amulet/core/block/block.hpp +156 -0
  13. amulet/core/block_entity/__init__.pyi +78 -0
  14. amulet/core/block_entity/block_entity.hpp +84 -0
  15. amulet/core/chunk/__init__.pyi +67 -0
  16. amulet/core/chunk/chunk.hpp +126 -0
  17. amulet/core/chunk/component/__init__.pyi +15 -0
  18. amulet/core/chunk/component/biome_3d_component.hpp +99 -0
  19. amulet/core/chunk/component/block_component.hpp +101 -0
  20. amulet/core/chunk/component/block_component.pyi +28 -0
  21. amulet/core/chunk/component/block_entity_component.hpp +119 -0
  22. amulet/core/chunk/component/section_array_map.hpp +178 -0
  23. amulet/core/chunk/component/section_array_map.pyi +112 -0
  24. amulet/core/dll.hpp +21 -0
  25. amulet/core/entity/__init__.pyi +105 -0
  26. amulet/core/entity/entity.hpp +100 -0
  27. amulet/core/libamulet_core.dylib +0 -0
  28. amulet/core/palette/__init__.pyi +8 -0
  29. amulet/core/palette/biome_palette.hpp +65 -0
  30. amulet/core/palette/biome_palette.pyi +48 -0
  31. amulet/core/palette/block_palette.hpp +71 -0
  32. amulet/core/palette/block_palette.pyi +52 -0
  33. amulet/core/py.typed +0 -0
  34. amulet/core/selection/__init__.pyi +25 -0
  35. amulet/core/selection/box.hpp +97 -0
  36. amulet/core/selection/box.pyi +239 -0
  37. amulet/core/selection/box_group.hpp +89 -0
  38. amulet/core/selection/box_group.pyi +222 -0
  39. amulet/core/selection/cuboid.hpp +41 -0
  40. amulet/core/selection/cuboid.pyi +49 -0
  41. amulet/core/selection/ellipsoid.hpp +42 -0
  42. amulet/core/selection/ellipsoid.pyi +47 -0
  43. amulet/core/selection/shape.hpp +73 -0
  44. amulet/core/selection/shape.pyi +56 -0
  45. amulet/core/selection/shape_group.hpp +73 -0
  46. amulet/core/selection/shape_group.pyi +118 -0
  47. amulet/core/version/__init__.pyi +138 -0
  48. amulet/core/version/version.hpp +206 -0
  49. amulet_core-2.0.7a0.dist-info/METADATA +112 -0
  50. amulet_core-2.0.7a0.dist-info/RECORD +53 -0
  51. amulet_core-2.0.7a0.dist-info/WHEEL +5 -0
  52. amulet_core-2.0.7a0.dist-info/entry_points.txt +2 -0
  53. amulet_core-2.0.7a0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,38 @@
1
+ import logging as _logging
2
+
3
+ from . import _version
4
+
5
+ __version__ = _version.get_versions()["version"]
6
+
7
+ # init a default logger
8
+ _logging.basicConfig(level=_logging.INFO, format="%(levelname)s - %(message)s")
9
+
10
+
11
+ def _init() -> None:
12
+ import os
13
+ import sys
14
+ import ctypes
15
+
16
+ if sys.platform == "win32":
17
+ lib_path = os.path.join(os.path.dirname(__file__), "amulet_core.dll")
18
+ elif sys.platform == "darwin":
19
+ lib_path = os.path.join(os.path.dirname(__file__), "libamulet_core.dylib")
20
+ elif sys.platform == "linux":
21
+ lib_path = os.path.join(os.path.dirname(__file__), "libamulet_core.so")
22
+ else:
23
+ raise RuntimeError(f"Unsupported platform {sys.platform}")
24
+
25
+ # Import dependencies
26
+ import amulet.utils
27
+ import amulet.zlib
28
+ import amulet.nbt
29
+
30
+ # Load the shared library
31
+ ctypes.cdll.LoadLibrary(lib_path)
32
+
33
+ from ._amulet_core import init
34
+
35
+ init(sys.modules[__name__])
36
+
37
+
38
+ _init()
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ from . import (
4
+ _amulet_core,
5
+ _version,
6
+ biome,
7
+ block,
8
+ block_entity,
9
+ chunk,
10
+ entity,
11
+ palette,
12
+ selection,
13
+ version,
14
+ )
15
+
16
+ __all__: list[str] = [
17
+ "biome",
18
+ "block",
19
+ "block_entity",
20
+ "chunk",
21
+ "compiler_config",
22
+ "entity",
23
+ "palette",
24
+ "selection",
25
+ "version",
26
+ ]
27
+
28
+ def _init() -> None: ...
29
+
30
+ __version__: str
31
+ compiler_config: dict
@@ -0,0 +1,2 @@
1
+ def get_hook_dirs() -> list[str]:
2
+ return __path__
@@ -0,0 +1,4 @@
1
+ from PyInstaller.utils.hooks import collect_data_files, collect_submodules
2
+
3
+ hiddenimports = collect_submodules("amulet.core")
4
+ datas = collect_data_files("amulet.core")
@@ -0,0 +1,7 @@
1
+ from __future__ import annotations
2
+
3
+ import types
4
+
5
+ __all__: list[str] = ["init"]
6
+
7
+ def init(m: types.ModuleType) -> None: ...
@@ -0,0 +1,21 @@
1
+
2
+ # This file was generated by 'versioneer.py' (0.29) from
3
+ # revision-control system data, or from the parent directory name of an
4
+ # unpacked source archive. Distribution tarballs contain a pre-generated copy
5
+ # of this file.
6
+
7
+ import json
8
+
9
+ version_json = '''
10
+ {
11
+ "date": "2025-11-20T15:14:43+0000",
12
+ "dirty": false,
13
+ "error": null,
14
+ "full-revisionid": "ffdb0c69d97f35a4fd911063d8eef90f887901b7",
15
+ "version": "2.0.7a0"
16
+ }
17
+ ''' # END VERSION_JSON
18
+
19
+
20
+ def get_versions():
21
+ return json.loads(version_json)
@@ -0,0 +1,23 @@
1
+ if (NOT TARGET amulet_core)
2
+ message(STATUS "Finding amulet_core")
3
+
4
+ find_package(amulet_io CONFIG REQUIRED)
5
+ find_package(amulet_nbt CONFIG REQUIRED)
6
+ find_package(amulet_utils CONFIG REQUIRED)
7
+
8
+ set(amulet_core_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/../..")
9
+ find_library(amulet_core_LIBRARY NAMES amulet_core PATHS "${CMAKE_CURRENT_LIST_DIR}")
10
+ message(STATUS "amulet_core_LIBRARY: ${amulet_core_LIBRARY}")
11
+
12
+ add_library(amulet_core_bin SHARED IMPORTED)
13
+ set_target_properties(amulet_core_bin PROPERTIES
14
+ IMPORTED_IMPLIB "${amulet_core_LIBRARY}"
15
+ )
16
+
17
+ add_library(amulet_core INTERFACE)
18
+ target_link_libraries(amulet_core INTERFACE amulet_io)
19
+ target_link_libraries(amulet_core INTERFACE amulet_nbt)
20
+ target_link_libraries(amulet_core INTERFACE amulet_utils)
21
+ target_link_libraries(amulet_core INTERFACE amulet_core_bin)
22
+ target_include_directories(amulet_core INTERFACE ${amulet_core_INCLUDE_DIR})
23
+ endif()
@@ -0,0 +1,75 @@
1
+ from __future__ import annotations
2
+
3
+ import types
4
+ import typing
5
+
6
+ import amulet.core.version
7
+
8
+ __all__: list[str] = ["Biome"]
9
+
10
+ class Biome(amulet.core.version.PlatformVersionContainer):
11
+ """
12
+ A class to manage the state of a biome.
13
+
14
+ It is an immutable object that contains the platform, version, namespace and base name.
15
+
16
+ Here's a few examples on how create a Biome object:
17
+
18
+ >>> # Create a plains biome for Java 1.20.2
19
+ >>> plains = Biome("java", VersionNumber(3578), "minecraft", "plains")
20
+ >>> # The version number for Java is the Java data version
21
+
22
+ >>> # Create a plains biome for Bedrock
23
+ >>> plains = Biome("bedrock", VersionNumber(1, 21, 0, 3), "minecraft", "plains")
24
+ >>> # The biome version number is unused in Bedrock but it is here for completeness.
25
+ """
26
+
27
+ @typing.overload
28
+ def __eq__(self, other: Biome) -> bool: ...
29
+ @typing.overload
30
+ def __eq__(self, other: typing.Any) -> bool | types.NotImplementedType: ...
31
+ def __ge__(self, arg0: Biome) -> bool: ...
32
+ def __gt__(self, arg0: Biome) -> bool: ...
33
+ def __hash__(self) -> int: ...
34
+ def __init__(
35
+ self,
36
+ platform: str,
37
+ version: amulet.core.version.VersionNumber,
38
+ namespace: str,
39
+ base_name: str,
40
+ ) -> None: ...
41
+ def __le__(self, arg0: Biome) -> bool: ...
42
+ def __lt__(self, arg0: Biome) -> bool: ...
43
+ def __repr__(self) -> str: ...
44
+ @property
45
+ def base_name(self) -> str:
46
+ """
47
+ The base name of the :class:`Biome` object.
48
+
49
+ >>> biome: Biome
50
+ >>> biome.base_name
51
+
52
+ :return: The base name of the biome
53
+ """
54
+
55
+ @property
56
+ def namespace(self) -> str:
57
+ """
58
+ The namespace of the :class:`Biome` object.
59
+
60
+ >>> biome: Biome
61
+ >>> water.namespace
62
+
63
+ :return: The namespace of the biome
64
+ """
65
+
66
+ @property
67
+ def namespaced_name(self) -> str:
68
+ """
69
+ The namespaced id of the :class:`Biome` object.
70
+
71
+ >>> biome: Biome
72
+ >>> biome.namespaced_name
73
+
74
+ :return: The "namespace:base_name" of the biome
75
+ """
@@ -0,0 +1,53 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+
5
+ #include <amulet/io/binary_reader.hpp>
6
+ #include <amulet/io/binary_writer.hpp>
7
+
8
+ #include <amulet/core/dll.hpp>
9
+ #include <amulet/core/version/version.hpp>
10
+
11
+ namespace Amulet {
12
+ class Biome : public PlatformVersionContainer {
13
+ private:
14
+ std::string _namespace;
15
+ std::string _base_name;
16
+
17
+ public:
18
+ const std::string& get_namespace() const { return _namespace; }
19
+ const std::string& get_base_name() const { return _base_name; }
20
+
21
+ template <typename PlatformT, typename VersionT, typename NamespaceT, typename BaseNameT>
22
+ Biome(
23
+ PlatformT&& platform,
24
+ VersionT&& version,
25
+ NamespaceT&& namespace_,
26
+ BaseNameT&& base_name)
27
+ : PlatformVersionContainer(std::forward<PlatformT>(platform), std::forward<VersionT>(version))
28
+ , _namespace(std::forward<NamespaceT>(namespace_))
29
+ , _base_name(std::forward<BaseNameT>(base_name))
30
+ {
31
+ }
32
+
33
+ AMULET_CORE_EXPORT void serialise(BinaryWriter&) const;
34
+ AMULET_CORE_EXPORT static Biome deserialise(BinaryReader&);
35
+
36
+ auto operator<=>(const Biome& other) const
37
+ {
38
+ auto cmp = PlatformVersionContainer::operator<=>(other);
39
+ if (cmp != 0) {
40
+ return cmp;
41
+ }
42
+ cmp = _namespace <=> other._namespace;
43
+ if (cmp != 0) {
44
+ return cmp;
45
+ }
46
+ return _base_name <=> other._base_name;
47
+ }
48
+ bool operator==(const Biome& other) const
49
+ {
50
+ return (*this <=> other) == 0;
51
+ }
52
+ };
53
+ }
@@ -0,0 +1,273 @@
1
+ from __future__ import annotations
2
+
3
+ import collections.abc
4
+ import types
5
+ import typing
6
+
7
+ import amulet.core.version
8
+ import amulet.nbt
9
+
10
+ __all__: list[str] = ["Block", "BlockStack"]
11
+
12
+ class Block(amulet.core.version.PlatformVersionContainer):
13
+ """
14
+ A class to manage the state of a block.
15
+
16
+ It is an immutable object that contains the platform, version, namespace, base name and properties.
17
+
18
+ Here's a few examples on how create a Block object:
19
+
20
+ >>> # Create a stone block for Java 1.20.2
21
+ >>> stone = Block("java", VersionNumber(3578), "minecraft", "stone")
22
+ >>> # The Java block version number is the Java data version
23
+
24
+ >>> # Create a stone block for Bedrock
25
+ >>> stone = Block("bedrock", VersionNumber(1, 21, 0, 3), "minecraft", "stone")
26
+ >>> # The Bedrock block version number is the value stored as an int with the block data.
27
+
28
+ >>> # Create a Java water block with the level property
29
+ >>> water = Block(
30
+ >>> "java", VersionNumber(3578),
31
+ >>> "minecraft", # the namespace
32
+ >>> "water", # the base name
33
+ >>> { # A dictionary of properties.
34
+ >>> # Keys must be strings and values must be a numerical or string NBT type.
35
+ >>> "level": StringTag("0") # define a property `level` with a string value `0`
36
+ >>> }
37
+ >>> )
38
+ """
39
+
40
+ PropertyValue: typing.TypeAlias = (
41
+ amulet.nbt.ByteTag
42
+ | amulet.nbt.ShortTag
43
+ | amulet.nbt.IntTag
44
+ | amulet.nbt.LongTag
45
+ | amulet.nbt.StringTag
46
+ )
47
+ @staticmethod
48
+ def from_bedrock_blockstate(
49
+ platform: str, version: amulet.core.version.VersionNumber, blockstate: str
50
+ ) -> Block:
51
+ """
52
+ Parse a Bedrock format blockstate where values are all strings and populate a :class:`Block` class with the data.
53
+
54
+ >>> stone = Block.from_bedrock_blockstate("minecraft:stone")
55
+ >>> water = Block.from_bedrock_blockstate("minecraft:water["liquid_depth"=0]")
56
+
57
+ :param platform: The platform the block is defined in.
58
+ :param version: The version the block is defined in.
59
+ :param blockstate: The Bedrock blockstate string to parse.
60
+ :return: A Block instance containing the state.
61
+ """
62
+
63
+ @staticmethod
64
+ def from_java_blockstate(
65
+ platform: str, version: amulet.core.version.VersionNumber, blockstate: str
66
+ ) -> Block:
67
+ """
68
+ Parse a Java format blockstate where values are all strings and populate a :class:`Block` class with the data.
69
+
70
+ >>> stone = Block.from_java_blockstate("minecraft:stone")
71
+ >>> water = Block.from_java_blockstate("minecraft:water[level=0]")
72
+
73
+ :param platform: The platform the block is defined in.
74
+ :param version: The version the block is defined in.
75
+ :param blockstate: The Java blockstate string to parse.
76
+ :return: A Block instance containing the state.
77
+ """
78
+
79
+ @typing.overload
80
+ def __eq__(self, other: Block) -> bool: ...
81
+ @typing.overload
82
+ def __eq__(self, other: typing.Any) -> bool | types.NotImplementedType: ...
83
+ def __ge__(self, arg0: Block) -> bool: ...
84
+ def __gt__(self, arg0: Block) -> bool: ...
85
+ def __hash__(self) -> int: ...
86
+ def __init__(
87
+ self,
88
+ platform: str,
89
+ version: amulet.core.version.VersionNumber,
90
+ namespace: str,
91
+ base_name: str,
92
+ properties: collections.abc.Mapping[
93
+ str,
94
+ amulet.nbt.ByteTag
95
+ | amulet.nbt.ShortTag
96
+ | amulet.nbt.IntTag
97
+ | amulet.nbt.LongTag
98
+ | amulet.nbt.StringTag,
99
+ ] = {},
100
+ ) -> None: ...
101
+ def __le__(self, arg0: Block) -> bool: ...
102
+ def __lt__(self, arg0: Block) -> bool: ...
103
+ def __repr__(self) -> str: ...
104
+ @property
105
+ def base_name(self) -> str:
106
+ """
107
+ The base name of the blockstate represented by the :class:`Block` object.
108
+
109
+ >>> block: Block
110
+ >>> block.base_name
111
+
112
+ :return: The base name of the blockstate
113
+ """
114
+
115
+ @property
116
+ def bedrock_blockstate(self) -> str:
117
+ """
118
+ The Bedrock blockstate string of this :class:`Block` object.
119
+ Converts the property values to the SNBT format to preserve type.
120
+
121
+ >>> bell = Block(
122
+ >>> "java", VersionNumber(3578),
123
+ >>> "minecraft",
124
+ >>> "bell",
125
+ >>> {
126
+ >>> "attachment":StringTag("standing"),
127
+ >>> "direction":IntTag(0),
128
+ >>> "toggle_bit":ByteTag(0)
129
+ >>> }
130
+ >>> )
131
+ >>> bell.bedrock_blockstate
132
+ minecraft:bell["attachment"="standing","direction"=0,"toggle_bit"=false]
133
+
134
+ :return: The SNBT blockstate string
135
+ """
136
+
137
+ @property
138
+ def java_blockstate(self) -> str:
139
+ """
140
+ The Java blockstate string of this :class:`Block` object.
141
+ Note this will only contain properties with StringTag values.
142
+
143
+ >>> stone = Block("java", VersionNumber(3578), "minecraft", "stone")
144
+ >>> stone.java_blockstate
145
+ minecraft:stone
146
+ >>> water = Block("java", VersionNumber(3578), "minecraft", "water", {"level": StringTag("0")})
147
+ >>> water.java_blockstate
148
+ minecraft:water[level=0]
149
+
150
+ :return: The blockstate string
151
+ """
152
+
153
+ @property
154
+ def namespace(self) -> str:
155
+ """
156
+ The namespace of the blockstate represented by the :class:`Block` object.
157
+
158
+ >>> block: Block
159
+ >>> water.namespace
160
+
161
+ :return: The namespace of the blockstate
162
+ """
163
+
164
+ @property
165
+ def namespaced_name(self) -> str:
166
+ """
167
+ The namespace:base_name of the blockstate represented by the :class:`Block` object.
168
+
169
+ >>> block: Block
170
+ >>> block.namespaced_name
171
+
172
+ :return: The namespace:base_name of the blockstate
173
+ """
174
+
175
+ @property
176
+ def properties(
177
+ self,
178
+ ) -> dict[
179
+ str,
180
+ amulet.nbt.ByteTag
181
+ | amulet.nbt.ShortTag
182
+ | amulet.nbt.IntTag
183
+ | amulet.nbt.LongTag
184
+ | amulet.nbt.StringTag,
185
+ ]:
186
+ """
187
+ The properties of the blockstate represented by the :class:`Block` object as a dictionary.
188
+ >>> block: Block
189
+ >>> block.properties
190
+
191
+ :return: A mapping of the properties of the blockstate
192
+ """
193
+
194
+ class BlockStack:
195
+ """
196
+ A stack of block objects.
197
+
198
+ Java 1.13 added the concept of waterlogging blocks whereby some blocks have a `waterlogged` property.
199
+ Bedrock achieved the same behaviour by added a layering system which allows the second block to be any block.
200
+
201
+ Amulet supports both implementations with a stack of one or more block objects similar to how Bedrock handles it.
202
+ Amulet places no restrictions on which blocks can be extra blocks.
203
+ Extra block may be discarded if the format does not support them.
204
+
205
+ Create a waterlogged stone block.
206
+ >>> waterlogged_stone = BlockStack(
207
+ >>> Block("java", VersionNumber(3578), "minecraft", "stone"),
208
+ >>> Block("java", VersionNumber(3578), "minecraft", "water", {"level": StringTag("0")})
209
+ >>> )
210
+
211
+ Get a block at an index
212
+ >>> stone = waterlogged_stone[0]
213
+ >>> water = waterlogged_stone[1]
214
+
215
+ Get the blocks as a list
216
+ >>> blocks = list(waterlogged_stone)
217
+ """
218
+
219
+ def __contains__(self, item: typing.Any) -> bool: ...
220
+ @typing.overload
221
+ def __eq__(self, other: BlockStack) -> bool: ...
222
+ @typing.overload
223
+ def __eq__(self, other: typing.Any) -> bool | types.NotImplementedType: ...
224
+ def __ge__(self, arg0: BlockStack) -> bool: ...
225
+ @typing.overload
226
+ def __getitem__(self, arg0: typing.SupportsInt) -> Block: ...
227
+ @typing.overload
228
+ def __getitem__(self, item: slice) -> list[Block]: ...
229
+ def __gt__(self, arg0: BlockStack) -> bool: ...
230
+ def __hash__(self) -> int: ...
231
+ def __init__(self, block: Block, *extra_blocks: Block) -> None: ...
232
+ def __iter__(self) -> collections.abc.Iterator[Block]: ...
233
+ def __le__(self, arg0: BlockStack) -> bool: ...
234
+ def __len__(self) -> int: ...
235
+ def __lt__(self, arg0: BlockStack) -> bool: ...
236
+ def __repr__(self) -> str: ...
237
+ def __reversed__(self) -> collections.abc.Iterator[Block]: ...
238
+ def count(self, value: Block) -> int: ...
239
+ def index(
240
+ self,
241
+ value: Block,
242
+ start: typing.SupportsInt = 0,
243
+ stop: typing.SupportsInt = 9223372036854775807,
244
+ ) -> int: ...
245
+ @property
246
+ def base_block(self) -> Block:
247
+ """
248
+ The first block in the stack.
249
+
250
+ >>> waterlogged_stone = BlockStack(
251
+ >>> Block("java", VersionNumber(3578), "minecraft", "stone"),
252
+ >>> Block("java", VersionNumber(3578), "minecraft", "water", {"level": StringTag("0")})
253
+ >>> )
254
+ >>> waterlogged_stone.base_block
255
+ Block("java", VersionNumber(3578), "minecraft", "stone")
256
+
257
+ :return: A Block object
258
+ """
259
+
260
+ @property
261
+ def extra_blocks(self) -> tuple[Block]:
262
+ """
263
+ The extra blocks in the stack.
264
+
265
+ >>> waterlogged_stone = BlockStack(
266
+ >>> Block("java", VersionNumber(3578), "minecraft", "stone"),
267
+ >>> Block("java", VersionNumber(3578), "minecraft", "water", {"level": StringTag("0")})
268
+ >>> )
269
+ >>> waterlogged_stone.extra_blocks
270
+ (Block("java", VersionNumber(3578), "minecraft", "water", {"level": StringTag("0")}),)
271
+
272
+ :return: A tuple of :class:`Block` objects
273
+ """
@@ -0,0 +1,156 @@
1
+ #pragma once
2
+
3
+ #include <map>
4
+ #include <string>
5
+ #include <variant>
6
+
7
+ #include <amulet/io/binary_reader.hpp>
8
+ #include <amulet/io/binary_writer.hpp>
9
+
10
+ #include <amulet/nbt/tag/int.hpp>
11
+ #include <amulet/nbt/tag/string.hpp>
12
+
13
+ #include <amulet/core/dll.hpp>
14
+ #include <amulet/core/version/version.hpp>
15
+
16
+ namespace Amulet {
17
+
18
+ class Block : public PlatformVersionContainer {
19
+ public:
20
+ using PropertyValue = std::variant<
21
+ Amulet::NBT::ByteTag,
22
+ Amulet::NBT::ShortTag,
23
+ Amulet::NBT::IntTag,
24
+ Amulet::NBT::LongTag,
25
+ Amulet::NBT::StringTag>;
26
+
27
+ using PropertyMap = std::map<std::string, PropertyValue>;
28
+
29
+ private:
30
+ std::string _namespace;
31
+ std::string _base_name;
32
+ PropertyMap _properties;
33
+
34
+ public:
35
+ const std::string& get_namespace() const { return _namespace; }
36
+ const std::string& get_base_name() const { return _base_name; }
37
+ const PropertyMap& get_properties() const { return _properties; }
38
+
39
+ template <
40
+ typename PlatformT,
41
+ typename VersionT,
42
+ typename NamespaceT,
43
+ typename BaseNameT>
44
+ Block(
45
+ PlatformT&& platform,
46
+ VersionT&& version,
47
+ NamespaceT&& namespace_,
48
+ BaseNameT&& base_name)
49
+ : PlatformVersionContainer(std::forward<PlatformT>(platform), std::forward<VersionT>(version))
50
+ , _namespace(std::forward<NamespaceT>(namespace_))
51
+ , _base_name(std::forward<BaseNameT>(base_name))
52
+ , _properties()
53
+ {
54
+ }
55
+
56
+ template <
57
+ typename PlatformT,
58
+ typename VersionT,
59
+ typename NamespaceT,
60
+ typename BaseNameT,
61
+ typename PropertiesT>
62
+ Block(
63
+ PlatformT&& platform,
64
+ VersionT&& version,
65
+ NamespaceT&& namespace_,
66
+ BaseNameT&& base_name,
67
+ PropertiesT&& properties)
68
+ : PlatformVersionContainer(std::forward<PlatformT>(platform), std::forward<VersionT>(version))
69
+ , _namespace(std::forward<NamespaceT>(namespace_))
70
+ , _base_name(std::forward<BaseNameT>(base_name))
71
+ , _properties(std::forward<PropertiesT>(properties))
72
+ {
73
+ }
74
+
75
+ AMULET_CORE_EXPORT void serialise(BinaryWriter&) const;
76
+ AMULET_CORE_EXPORT static Block deserialise(BinaryReader&);
77
+
78
+ auto operator<=>(const Block& other) const
79
+ {
80
+ auto cmp = PlatformVersionContainer::operator<=>(other);
81
+ if (cmp != 0) {
82
+ return cmp;
83
+ }
84
+ cmp = _namespace <=> other._namespace;
85
+ if (cmp != 0) {
86
+ return cmp;
87
+ }
88
+ cmp = _base_name <=> other._base_name;
89
+ if (cmp != 0) {
90
+ return cmp;
91
+ }
92
+ return _properties <=> other._properties;
93
+ }
94
+ bool operator==(const Block& other) const
95
+ {
96
+ return (*this <=> other) == 0;
97
+ }
98
+
99
+ AMULET_CORE_EXPORT std::string java_blockstate() const;
100
+ AMULET_CORE_EXPORT std::string bedrock_blockstate() const;
101
+ AMULET_CORE_EXPORT static Block from_java_blockstate(const PlatformType&, const VersionNumber&, const std::string&);
102
+ AMULET_CORE_EXPORT static Block from_bedrock_blockstate(const PlatformType&, const VersionNumber&, const std::string&);
103
+ };
104
+
105
+ class BlockStack {
106
+ private:
107
+ std::vector<Block> _blocks;
108
+
109
+ public:
110
+ const std::vector<Block>& get_blocks() const { return _blocks; }
111
+
112
+ template <typename... Args>
113
+ requires std::is_constructible_v<std::vector<Block>, Args...>
114
+ BlockStack(Args&&... args)
115
+ : _blocks(std::forward<Args>(args)...)
116
+ {
117
+ if (_blocks.empty()) {
118
+ throw std::invalid_argument("A BlockStack must contain at least one block");
119
+ }
120
+ }
121
+
122
+ BlockStack(std::initializer_list<Block> blocks)
123
+ : _blocks(blocks)
124
+ {
125
+ if (_blocks.empty()) {
126
+ throw std::invalid_argument("A BlockStack must contain at least one block");
127
+ }
128
+ }
129
+
130
+ AMULET_CORE_EXPORT void serialise(BinaryWriter&) const;
131
+ AMULET_CORE_EXPORT static BlockStack deserialise(BinaryReader&);
132
+
133
+ auto operator<=>(const BlockStack& other) const
134
+ {
135
+ auto cmp = size() <=> other.size();
136
+ if (cmp != 0) {
137
+ return cmp;
138
+ }
139
+ for (size_t i = 0; i < size(); i++) {
140
+ cmp = at(i) <=> other.at(i);
141
+ if (cmp != 0) {
142
+ return cmp;
143
+ }
144
+ }
145
+ return std::strong_ordering::equal;
146
+ }
147
+ bool operator==(const BlockStack& other) const
148
+ {
149
+ return (*this <=> other) == 0;
150
+ }
151
+
152
+ size_t size() const { return _blocks.size(); }
153
+ const Block& at(size_t index) const { return _blocks.at(index); }
154
+ };
155
+
156
+ } // namespace Amulet