amulet-core 2.0.4a1.post250728120927__cp312-cp312-win_amd64.whl → 2.0.5a1__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of amulet-core might be problematic. Click here for more details.

Files changed (40) hide show
  1. amulet/core/__init__.py +1 -0
  2. amulet/core/__init__.pyi +1 -1
  3. amulet/core/_amulet_core.cp312-win_amd64.pyd +0 -0
  4. amulet/core/_amulet_core.pyi +1 -1
  5. amulet/core/_version.py +3 -3
  6. amulet/core/amulet_core.dll +0 -0
  7. amulet/core/amulet_core.lib +0 -0
  8. amulet/core/amulet_coreConfig.cmake +2 -0
  9. amulet/core/biome/__init__.pyi +3 -3
  10. amulet/core/block/__init__.pyi +9 -9
  11. amulet/core/block_entity/__init__.pyi +3 -3
  12. amulet/core/chunk/__init__.pyi +1 -1
  13. amulet/core/chunk/component/__init__.pyi +1 -1
  14. amulet/core/chunk/component/block_component.pyi +1 -1
  15. amulet/core/chunk/component/section_array_map.pyi +42 -26
  16. amulet/core/entity/__init__.pyi +3 -3
  17. amulet/core/palette/__init__.pyi +1 -1
  18. amulet/core/palette/biome_palette.pyi +6 -6
  19. amulet/core/palette/block_palette.pyi +4 -4
  20. amulet/core/selection/__init__.pyi +20 -3
  21. amulet/core/selection/box.hpp +27 -16
  22. amulet/core/selection/box.pyi +20 -10
  23. amulet/core/selection/box_group.hpp +89 -0
  24. amulet/core/selection/{group.pyi → box_group.pyi} +34 -33
  25. amulet/core/selection/cuboid.hpp +41 -0
  26. amulet/core/selection/cuboid.pyi +49 -0
  27. amulet/core/selection/ellipsoid.hpp +42 -0
  28. amulet/core/selection/ellipsoid.pyi +47 -0
  29. amulet/core/selection/shape.hpp +73 -0
  30. amulet/core/selection/shape.pyi +56 -0
  31. amulet/core/selection/shape_group.hpp +73 -0
  32. amulet/core/selection/shape_group.pyi +118 -0
  33. amulet/core/version/__init__.pyi +5 -5
  34. {amulet_core-2.0.4a1.post250728120927.dist-info → amulet_core-2.0.5a1.dist-info}/METADATA +7 -7
  35. amulet_core-2.0.5a1.dist-info/RECORD +54 -0
  36. amulet/core/selection/group.hpp +0 -80
  37. amulet_core-2.0.4a1.post250728120927.dist-info/RECORD +0 -46
  38. {amulet_core-2.0.4a1.post250728120927.dist-info → amulet_core-2.0.5a1.dist-info}/WHEEL +0 -0
  39. {amulet_core-2.0.4a1.post250728120927.dist-info → amulet_core-2.0.5a1.dist-info}/entry_points.txt +0 -0
  40. {amulet_core-2.0.4a1.post250728120927.dist-info → amulet_core-2.0.5a1.dist-info}/top_level.txt +0 -0
amulet/core/__init__.py CHANGED
@@ -23,6 +23,7 @@ def _init() -> None:
23
23
  raise RuntimeError(f"Unsupported platform {sys.platform}")
24
24
 
25
25
  # Import dependencies
26
+ import amulet.utils
26
27
  import amulet.zlib
27
28
  import amulet.nbt
28
29
 
amulet/core/__init__.pyi CHANGED
@@ -13,7 +13,7 @@ from . import (
13
13
  version,
14
14
  )
15
15
 
16
- __all__ = [
16
+ __all__: list[str] = [
17
17
  "biome",
18
18
  "block",
19
19
  "block_entity",
@@ -2,6 +2,6 @@ from __future__ import annotations
2
2
 
3
3
  import types
4
4
 
5
- __all__ = ["init"]
5
+ __all__: list[str] = ["init"]
6
6
 
7
7
  def init(arg0: types.ModuleType) -> None: ...
amulet/core/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2025-07-28T13:06:55+0100",
11
+ "date": "2025-09-17T11:29:24+0100",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "9f6478cecb25ca0c0779bb4bf851c1a4ee0771cf",
15
- "version": "2.0.4a1"
14
+ "full-revisionid": "7ed2b2b5421e7cb0691779cf4861faf812f8cee3",
15
+ "version": "2.0.5a1"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
Binary file
Binary file
@@ -3,6 +3,7 @@ if (NOT TARGET amulet_core)
3
3
 
4
4
  find_package(amulet_io CONFIG REQUIRED)
5
5
  find_package(amulet_nbt CONFIG REQUIRED)
6
+ find_package(amulet_utils CONFIG REQUIRED)
6
7
 
7
8
  set(amulet_core_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/../..")
8
9
  find_library(amulet_core_LIBRARY NAMES amulet_core PATHS "${CMAKE_CURRENT_LIST_DIR}")
@@ -16,6 +17,7 @@ if (NOT TARGET amulet_core)
16
17
  add_library(amulet_core INTERFACE)
17
18
  target_link_libraries(amulet_core INTERFACE amulet_io)
18
19
  target_link_libraries(amulet_core INTERFACE amulet_nbt)
20
+ target_link_libraries(amulet_core INTERFACE amulet_utils)
19
21
  target_link_libraries(amulet_core INTERFACE amulet_core_bin)
20
22
  target_include_directories(amulet_core INTERFACE ${amulet_core_INCLUDE_DIR})
21
23
  endif()
@@ -5,7 +5,7 @@ import typing
5
5
 
6
6
  import amulet.core.version
7
7
 
8
- __all__ = ["Biome"]
8
+ __all__: list[str] = ["Biome"]
9
9
 
10
10
  class Biome(amulet.core.version.PlatformVersionContainer):
11
11
  """
@@ -25,9 +25,9 @@ class Biome(amulet.core.version.PlatformVersionContainer):
25
25
  """
26
26
 
27
27
  @typing.overload
28
- def __eq__(self, arg0: Biome) -> bool: ...
28
+ def __eq__(self, other: Biome) -> bool: ...
29
29
  @typing.overload
30
- def __eq__(self, arg0: typing.Any) -> bool | types.NotImplementedType: ...
30
+ def __eq__(self, other: typing.Any) -> bool | types.NotImplementedType: ...
31
31
  def __ge__(self, arg0: Biome) -> bool: ...
32
32
  def __gt__(self, arg0: Biome) -> bool: ...
33
33
  def __hash__(self) -> int: ...
@@ -7,7 +7,7 @@ import typing
7
7
  import amulet.core.version
8
8
  import amulet.nbt
9
9
 
10
- __all__ = ["Block", "BlockStack"]
10
+ __all__: list[str] = ["Block", "BlockStack"]
11
11
 
12
12
  class Block(amulet.core.version.PlatformVersionContainer):
13
13
  """
@@ -77,9 +77,9 @@ class Block(amulet.core.version.PlatformVersionContainer):
77
77
  """
78
78
 
79
79
  @typing.overload
80
- def __eq__(self, arg0: Block) -> bool: ...
80
+ def __eq__(self, other: Block) -> bool: ...
81
81
  @typing.overload
82
- def __eq__(self, arg0: typing.Any) -> bool | types.NotImplementedType: ...
82
+ def __eq__(self, other: typing.Any) -> bool | types.NotImplementedType: ...
83
83
  def __ge__(self, arg0: Block) -> bool: ...
84
84
  def __gt__(self, arg0: Block) -> bool: ...
85
85
  def __hash__(self) -> int: ...
@@ -216,16 +216,16 @@ class BlockStack:
216
216
  >>> blocks = list(waterlogged_stone)
217
217
  """
218
218
 
219
- def __contains__(self, arg0: typing.Any) -> bool: ...
219
+ def __contains__(self, item: typing.Any) -> bool: ...
220
220
  @typing.overload
221
- def __eq__(self, arg0: BlockStack) -> bool: ...
221
+ def __eq__(self, other: BlockStack) -> bool: ...
222
222
  @typing.overload
223
- def __eq__(self, arg0: typing.Any) -> bool | types.NotImplementedType: ...
223
+ def __eq__(self, other: typing.Any) -> bool | types.NotImplementedType: ...
224
224
  def __ge__(self, arg0: BlockStack) -> bool: ...
225
225
  @typing.overload
226
226
  def __getitem__(self, arg0: typing.SupportsInt) -> Block: ...
227
227
  @typing.overload
228
- def __getitem__(self, arg0: slice) -> list: ...
228
+ def __getitem__(self, item: slice) -> list[Block]: ...
229
229
  def __gt__(self, arg0: BlockStack) -> bool: ...
230
230
  def __hash__(self) -> int: ...
231
231
  def __init__(self, block: Block, *extra_blocks: Block) -> None: ...
@@ -235,10 +235,10 @@ class BlockStack:
235
235
  def __lt__(self, arg0: BlockStack) -> bool: ...
236
236
  def __repr__(self) -> str: ...
237
237
  def __reversed__(self) -> collections.abc.Iterator[Block]: ...
238
- def count(self, value: typing.Any) -> int: ...
238
+ def count(self, value: Block) -> int: ...
239
239
  def index(
240
240
  self,
241
- value: typing.Any,
241
+ value: Block,
242
242
  start: typing.SupportsInt = 0,
243
243
  stop: typing.SupportsInt = 9223372036854775807,
244
244
  ) -> int: ...
@@ -6,7 +6,7 @@ import typing
6
6
  import amulet.core.version
7
7
  import amulet.nbt
8
8
 
9
- __all__ = ["BlockEntity"]
9
+ __all__: list[str] = ["BlockEntity"]
10
10
 
11
11
  class BlockEntity(amulet.core.version.PlatformVersionContainer):
12
12
  """
@@ -14,9 +14,9 @@ class BlockEntity(amulet.core.version.PlatformVersionContainer):
14
14
  """
15
15
 
16
16
  @typing.overload
17
- def __eq__(self, arg0: BlockEntity) -> bool: ...
17
+ def __eq__(self, other: BlockEntity) -> bool: ...
18
18
  @typing.overload
19
- def __eq__(self, arg0: typing.Any) -> bool | types.NotImplementedType: ...
19
+ def __eq__(self, other: typing.Any) -> bool | types.NotImplementedType: ...
20
20
  def __hash__(self) -> int: ...
21
21
  def __init__(
22
22
  self,
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from . import component
4
4
 
5
- __all__ = [
5
+ __all__: list[str] = [
6
6
  "Chunk",
7
7
  "ChunkDoesNotExist",
8
8
  "ChunkLoadError",
@@ -8,7 +8,7 @@ from amulet.core.chunk.component.section_array_map import IndexArray3D, SectionA
8
8
 
9
9
  from . import block_component, section_array_map
10
10
 
11
- __all__ = [
11
+ __all__: list[str] = [
12
12
  "BlockComponent",
13
13
  "BlockComponentData",
14
14
  "IndexArray3D",
@@ -7,7 +7,7 @@ import amulet.core.chunk.component.section_array_map
7
7
  import amulet.core.palette.block_palette
8
8
  import amulet.core.version
9
9
 
10
- __all__ = ["BlockComponent", "BlockComponentData"]
10
+ __all__: list[str] = ["BlockComponent", "BlockComponentData"]
11
11
 
12
12
  class BlockComponent:
13
13
  ComponentID: typing.ClassVar[str] = "Amulet::BlockComponent"
@@ -7,7 +7,7 @@ import typing
7
7
  import numpy
8
8
  import numpy.typing
9
9
 
10
- __all__ = ["IndexArray3D", "SectionArrayMap"]
10
+ __all__: list[str] = ["IndexArray3D", "SectionArrayMap"]
11
11
 
12
12
  class IndexArray3D:
13
13
  """
@@ -40,7 +40,7 @@ class SectionArrayMap:
40
40
 
41
41
  def __contains__(self, arg0: typing.SupportsInt) -> bool: ...
42
42
  def __delitem__(self, arg0: typing.SupportsInt) -> None: ...
43
- def __eq__(self, arg0: typing.Any) -> bool | types.NotImplementedType: ...
43
+ def __eq__(self, other: typing.Any) -> bool | types.NotImplementedType: ...
44
44
  def __getitem__(
45
45
  self, arg0: typing.SupportsInt
46
46
  ) -> numpy.typing.NDArray[numpy.uint32]: ...
@@ -48,40 +48,61 @@ class SectionArrayMap:
48
48
  def __init__(
49
49
  self,
50
50
  array_shape: tuple[typing.SupportsInt, typing.SupportsInt, typing.SupportsInt],
51
- default_array: (
52
- typing.SupportsInt
53
- | amulet.core.chunk.component.section_array_map.IndexArray3D
54
- | collections.abc.Buffer
55
- ),
51
+ default_array: typing.SupportsInt | IndexArray3D | collections.abc.Buffer,
56
52
  ) -> None: ...
57
53
  def __iter__(self) -> collections.abc.Iterator[int]: ...
58
54
  def __len__(self) -> int: ...
59
55
  def __setitem__(
60
- self,
61
- arg0: typing.SupportsInt,
62
- arg1: (
63
- amulet.core.chunk.component.section_array_map.IndexArray3D
64
- | collections.abc.Buffer
65
- ),
56
+ self, arg0: typing.SupportsInt, arg1: IndexArray3D | collections.abc.Buffer
66
57
  ) -> None: ...
58
+ @typing.overload
67
59
  def get(
68
- self,
69
- key: typing.SupportsInt,
70
- default: numpy.typing.NDArray[numpy.uint32] | None = None,
60
+ self, key: typing.SupportsInt
71
61
  ) -> numpy.typing.NDArray[numpy.uint32] | None: ...
62
+ @typing.overload
63
+ def get(
64
+ self, key: typing.SupportsInt, default: numpy.typing.NDArray[numpy.uint32]
65
+ ) -> numpy.typing.NDArray[numpy.uint32]: ...
66
+ @typing.overload
67
+ def get[T](
68
+ self, key: typing.SupportsInt, default: T
69
+ ) -> numpy.typing.NDArray[numpy.uint32] | T: ...
72
70
  def items(
73
71
  self,
74
72
  ) -> collections.abc.ItemsView[int, numpy.typing.NDArray[numpy.uint32]]: ...
75
73
  def keys(self) -> collections.abc.KeysView[int]: ...
74
+ @typing.overload
75
+ def pop(self, key: typing.SupportsInt) -> numpy.typing.NDArray[numpy.uint32]: ...
76
+ @typing.overload
76
77
  def pop(
77
- self, key: typing.SupportsInt, default: numpy.typing.NDArray[numpy.uint32] = ...
78
+ self, key: typing.SupportsInt, default: numpy.typing.NDArray[numpy.uint32]
78
79
  ) -> numpy.typing.NDArray[numpy.uint32]: ...
80
+ @typing.overload
81
+ def pop[T](
82
+ self, key: typing.SupportsInt, default: T
83
+ ) -> numpy.typing.NDArray[numpy.uint32] | T: ...
79
84
  def popitem(self) -> tuple[int, numpy.typing.NDArray[numpy.uint32]]: ...
80
85
  def populate(self, arg0: typing.SupportsInt) -> None: ...
86
+ @typing.overload
81
87
  def setdefault(
82
- self, arg0: typing.SupportsInt, arg1: numpy.typing.NDArray[numpy.uint32] | None
83
- ) -> numpy.typing.NDArray[numpy.uint32] | None: ...
84
- def update(self, other: typing.Any = (), **kwargs: typing.Any) -> None: ...
88
+ self, key: typing.SupportsInt
89
+ ) -> numpy.typing.NDArray[numpy.uint32]: ...
90
+ @typing.overload
91
+ def setdefault(
92
+ self, key: typing.SupportsInt, default: numpy.typing.NDArray[numpy.uint32]
93
+ ) -> numpy.typing.NDArray[numpy.uint32]: ...
94
+ def update(
95
+ self,
96
+ other: (
97
+ collections.abc.Mapping[
98
+ typing.SupportsInt, numpy.typing.NDArray[numpy.uint32]
99
+ ]
100
+ | collections.abc.Iterable[
101
+ tuple[typing.SupportsInt, numpy.typing.NDArray[numpy.uint32]]
102
+ ]
103
+ ) = (),
104
+ **kwargs: numpy.typing.NDArray[numpy.uint32],
105
+ ) -> None: ...
85
106
  def values(
86
107
  self,
87
108
  ) -> collections.abc.ValuesView[numpy.typing.NDArray[numpy.uint32]]: ...
@@ -91,10 +112,5 @@ class SectionArrayMap:
91
112
  def default_array(self) -> int | numpy.ndarray: ...
92
113
  @default_array.setter
93
114
  def default_array(
94
- self,
95
- arg1: (
96
- typing.SupportsInt
97
- | amulet.core.chunk.component.section_array_map.IndexArray3D
98
- | collections.abc.Buffer
99
- ),
115
+ self, arg1: typing.SupportsInt | IndexArray3D | collections.abc.Buffer
100
116
  ) -> None: ...
@@ -6,7 +6,7 @@ import typing
6
6
  import amulet.core.version
7
7
  import amulet.nbt
8
8
 
9
- __all__ = ["Entity"]
9
+ __all__: list[str] = ["Entity"]
10
10
 
11
11
  class Entity(amulet.core.version.PlatformVersionContainer):
12
12
  """
@@ -14,9 +14,9 @@ class Entity(amulet.core.version.PlatformVersionContainer):
14
14
  """
15
15
 
16
16
  @typing.overload
17
- def __eq__(self, arg0: Entity) -> bool: ...
17
+ def __eq__(self, other: Entity) -> bool: ...
18
18
  @typing.overload
19
- def __eq__(self, arg0: typing.Any) -> bool | types.NotImplementedType: ...
19
+ def __eq__(self, other: typing.Any) -> bool | types.NotImplementedType: ...
20
20
  def __hash__(self) -> int: ...
21
21
  def __init__(
22
22
  self,
@@ -5,4 +5,4 @@ from amulet.core.palette.block_palette import BlockPalette
5
5
 
6
6
  from . import biome_palette, block_palette
7
7
 
8
- __all__ = ["BiomePalette", "BlockPalette", "biome_palette", "block_palette"]
8
+ __all__: list[str] = ["BiomePalette", "BlockPalette", "biome_palette", "block_palette"]
@@ -6,7 +6,7 @@ import typing
6
6
  import amulet.core.biome
7
7
  import amulet.core.version
8
8
 
9
- __all__ = ["BiomePalette"]
9
+ __all__: list[str] = ["BiomePalette"]
10
10
 
11
11
  class BiomePalette(amulet.core.version.VersionRangeContainer):
12
12
  @typing.overload
@@ -16,12 +16,12 @@ class BiomePalette(amulet.core.version.VersionRangeContainer):
16
16
  @typing.overload
17
17
  def __getitem__(self, arg0: typing.SupportsInt) -> amulet.core.biome.Biome: ...
18
18
  @typing.overload
19
- def __getitem__(self, arg0: slice) -> list: ...
19
+ def __getitem__(self, item: slice) -> list[amulet.core.biome.Biome]: ...
20
20
  def __init__(self, arg0: amulet.core.version.VersionRange) -> None: ...
21
- def __iter__(self) -> collections.abc.Iterator[typing.Any]: ...
21
+ def __iter__(self) -> collections.abc.Iterator[amulet.core.biome.Biome]: ...
22
22
  def __len__(self) -> int: ...
23
23
  def __repr__(self) -> str: ...
24
- def __reversed__(self) -> collections.abc.Iterator[typing.Any]: ...
24
+ def __reversed__(self) -> collections.abc.Iterator[amulet.core.biome.Biome]: ...
25
25
  def biome_to_index(self, arg0: amulet.core.biome.Biome) -> int:
26
26
  """
27
27
  Get the index of the biome in the palette.
@@ -31,10 +31,10 @@ class BiomePalette(amulet.core.version.VersionRangeContainer):
31
31
  :return: The index of the biome in the palette.
32
32
  """
33
33
 
34
- def count(self, value: typing.Any) -> int: ...
34
+ def count(self, value: amulet.core.biome.Biome) -> int: ...
35
35
  def index(
36
36
  self,
37
- value: typing.Any,
37
+ value: amulet.core.biome.Biome,
38
38
  start: typing.SupportsInt = 0,
39
39
  stop: typing.SupportsInt = 9223372036854775807,
40
40
  ) -> int: ...
@@ -6,7 +6,7 @@ import typing
6
6
  import amulet.core.block
7
7
  import amulet.core.version
8
8
 
9
- __all__ = ["BlockPalette"]
9
+ __all__: list[str] = ["BlockPalette"]
10
10
 
11
11
  class BlockPalette(amulet.core.version.VersionRangeContainer):
12
12
  @typing.overload
@@ -16,7 +16,7 @@ class BlockPalette(amulet.core.version.VersionRangeContainer):
16
16
  @typing.overload
17
17
  def __getitem__(self, arg0: typing.SupportsInt) -> amulet.core.block.BlockStack: ...
18
18
  @typing.overload
19
- def __getitem__(self, arg0: slice) -> list: ...
19
+ def __getitem__(self, item: slice) -> list[amulet.core.block.BlockStack]: ...
20
20
  def __init__(self, arg0: amulet.core.version.VersionRange) -> None: ...
21
21
  def __iter__(self) -> collections.abc.Iterator[amulet.core.block.BlockStack]: ...
22
22
  def __len__(self) -> int: ...
@@ -33,10 +33,10 @@ class BlockPalette(amulet.core.version.VersionRangeContainer):
33
33
  :return: The index of the block stack in the palette.
34
34
  """
35
35
 
36
- def count(self, value: typing.Any) -> int: ...
36
+ def count(self, value: amulet.core.block.BlockStack) -> int: ...
37
37
  def index(
38
38
  self,
39
- value: typing.Any,
39
+ value: amulet.core.block.BlockStack,
40
40
  start: typing.SupportsInt = 0,
41
41
  stop: typing.SupportsInt = 9223372036854775807,
42
42
  ) -> int: ...
@@ -1,8 +1,25 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from amulet.core.selection.box import SelectionBox
4
- from amulet.core.selection.group import SelectionGroup
4
+ from amulet.core.selection.box_group import SelectionBoxGroup
5
+ from amulet.core.selection.cuboid import SelectionCuboid
6
+ from amulet.core.selection.ellipsoid import SelectionEllipsoid
7
+ from amulet.core.selection.shape import SelectionShape
8
+ from amulet.core.selection.shape_group import SelectionShapeGroup
5
9
 
6
- from . import box, group
10
+ from . import box, box_group, cuboid, ellipsoid, shape, shape_group
7
11
 
8
- __all__ = ["SelectionBox", "SelectionGroup", "box", "group"]
12
+ __all__: list[str] = [
13
+ "SelectionBox",
14
+ "SelectionBoxGroup",
15
+ "SelectionCuboid",
16
+ "SelectionEllipsoid",
17
+ "SelectionShape",
18
+ "SelectionShapeGroup",
19
+ "box",
20
+ "box_group",
21
+ "cuboid",
22
+ "ellipsoid",
23
+ "shape",
24
+ "shape_group",
25
+ ]
@@ -6,10 +6,11 @@
6
6
 
7
7
  namespace Amulet {
8
8
 
9
- class SelectionGroup;
9
+ class Matrix4x4;
10
+ class SelectionBoxGroup;
10
11
 
11
- // The SelectionBox class represents a single cuboid selection.
12
- class SelectionBox {
12
+ // An axis aligned cuboid selection box.
13
+ class AMULET_CORE_EXPORT SelectionBox {
13
14
  private:
14
15
  std::int64_t _min_x;
15
16
  std::int64_t _min_y;
@@ -47,6 +48,17 @@ public:
47
48
  _size_z = std::max(point_1[2], point_2[2]) - _min_z;
48
49
  }
49
50
 
51
+ SelectionBox(const SelectionBox& other)
52
+ : SelectionBox(
53
+ other.min_x(),
54
+ other.min_y(),
55
+ other.min_z(),
56
+ other.size_x(),
57
+ other.size_y(),
58
+ other.size_z())
59
+ {
60
+ }
61
+
50
62
  // Accessors
51
63
  std::int64_t min_x() const { return _min_x; }
52
64
  std::int64_t min_y() const { return _min_y; }
@@ -62,25 +74,24 @@ public:
62
74
  std::uint64_t size_y() const { return _size_y; }
63
75
  std::uint64_t size_z() const { return _size_z; }
64
76
  std::array<std::uint64_t, 3> shape() const { return { _size_x, _size_y, _size_z }; }
65
- size_t volume() const { return _size_x * _size_y * _size_z; }
77
+ std::uint64_t volume() const { return _size_x * _size_y * _size_z; }
66
78
 
67
79
  // Contains and intersects
68
- AMULET_CORE_EXPORT bool contains_block(std::int64_t x, std::int64_t y, std::int64_t z) const;
69
- AMULET_CORE_EXPORT bool contains_point(double x, double y, double z) const;
70
- AMULET_CORE_EXPORT bool contains_box(const SelectionBox& other) const;
71
- AMULET_CORE_EXPORT bool intersects(const SelectionBox& other) const;
72
- AMULET_CORE_EXPORT bool intersects(const SelectionGroup& other) const;
73
- AMULET_CORE_EXPORT bool touches_or_intersects(const SelectionBox& other) const;
74
- AMULET_CORE_EXPORT bool touches(const SelectionBox& other) const;
80
+ bool contains_block(std::int64_t x, std::int64_t y, std::int64_t z) const;
81
+ bool contains_point(double x, double y, double z) const;
82
+ bool contains_box(const SelectionBox& other) const;
83
+ bool intersects(const SelectionBox& other) const;
84
+ bool intersects(const SelectionBoxGroup& other) const;
85
+ bool touches_or_intersects(const SelectionBox& other) const;
86
+ bool touches(const SelectionBox& other) const;
75
87
 
76
88
  // Transform
77
- AMULET_CORE_EXPORT SelectionBox translate(std::int64_t dx, std::int64_t dy, std::int64_t dz) const;
78
- // AMULET_CORE_EXPORT SelectionGroup transform() const;
89
+ SelectionBox translate(std::int64_t dx, std::int64_t dy, std::int64_t dz) const;
90
+ SelectionBoxGroup transform(const Matrix4x4&) const;
79
91
 
80
92
  // Operators
81
- auto operator<=>(const SelectionBox&) const = default;
93
+ std::strong_ordering operator<=>(const SelectionBox&) const;
94
+ bool operator==(const SelectionBox&) const;
82
95
  };
83
96
 
84
97
  } // namespace Amulet
85
-
86
- #include "group.hpp"
@@ -3,21 +3,22 @@ from __future__ import annotations
3
3
  import types
4
4
  import typing
5
5
 
6
- import amulet.core.selection.group
6
+ import amulet.core.selection.box_group
7
+ import amulet.utils.matrix
7
8
 
8
- __all__ = ["SelectionBox"]
9
+ __all__: list[str] = ["SelectionBox"]
9
10
 
10
11
  class SelectionBox:
11
12
  """
12
13
  The SelectionBox class represents a single cuboid selection.
13
14
 
14
- When combined with :class:`~amulet.api.selection.SelectionGroup` it can represent any arbitrary shape.
15
+ When combined with :class:`~amulet.api.selection.SelectionBoxGroup` it can represent any arbitrary shape.
15
16
  """
16
17
 
17
18
  @typing.overload
18
- def __eq__(self, arg0: SelectionBox) -> bool: ...
19
+ def __eq__(self, other: SelectionBox) -> bool: ...
19
20
  @typing.overload
20
- def __eq__(self, arg0: typing.Any) -> bool | types.NotImplementedType: ...
21
+ def __eq__(self, other: typing.Any) -> bool | types.NotImplementedType: ...
21
22
  def __ge__(self, arg0: SelectionBox) -> bool: ...
22
23
  def __gt__(self, arg0: SelectionBox) -> bool: ...
23
24
  def __hash__(self) -> int: ...
@@ -115,7 +116,9 @@ class SelectionBox:
115
116
  """
116
117
 
117
118
  @typing.overload
118
- def intersects(self, other: amulet.core.selection.group.SelectionGroup) -> bool: ...
119
+ def intersects(
120
+ self, other: amulet.core.selection.box_group.SelectionBoxGroup
121
+ ) -> bool: ...
119
122
  def touches(self, other: SelectionBox) -> bool:
120
123
  """
121
124
  Method to check if this instance of :class:`SelectionBox` touches but does not intersect another SelectionBox.
@@ -132,15 +135,22 @@ class SelectionBox:
132
135
  :return: True if the two :class:`SelectionBox` instances touch or intersect, False otherwise.
133
136
  """
134
137
 
138
+ def transform(
139
+ self, matrix: amulet.utils.matrix.Matrix4x4
140
+ ) -> amulet.core.selection.box_group.SelectionBoxGroup:
141
+ """
142
+ Transform this box by the given transformation matrix.
143
+ """
144
+
135
145
  def translate(
136
- self, x: typing.SupportsInt, y: typing.SupportsInt, z: typing.SupportsInt
146
+ self, dx: typing.SupportsInt, dy: typing.SupportsInt, dz: typing.SupportsInt
137
147
  ) -> SelectionBox:
138
148
  """
139
149
  Create a new :class:`SelectionBox` based on this one with the coordinates moved by the given offset.
140
150
 
141
- :param x: The x offset.
142
- :param y: The y offset.
143
- :param z: The z offset.
151
+ :param dx: The x offset.
152
+ :param dy: The y offset.
153
+ :param dz: The z offset.
144
154
  :return: The new selection with the given offset.
145
155
  """
146
156
 
@@ -0,0 +1,89 @@
1
+ #pragma once
2
+
3
+ #include <array>
4
+ #include <concepts>
5
+ #include <ranges>
6
+ #include <set>
7
+
8
+ #include <amulet/core/dll.hpp>
9
+
10
+ #include "box.hpp"
11
+
12
+ namespace Amulet {
13
+
14
+ class AMULET_CORE_EXPORT SelectionBoxGroup {
15
+ private:
16
+ std::set<SelectionBox> _boxes;
17
+
18
+ public:
19
+ // Forwarding constructor
20
+ template <typename... Args>
21
+ SelectionBoxGroup(Args&&... args)
22
+ : _boxes(std::forward<Args>(args)...)
23
+ {
24
+ }
25
+
26
+ SelectionBoxGroup(std::initializer_list<SelectionBox> boxes)
27
+ : _boxes(boxes)
28
+ {
29
+ }
30
+
31
+ // Accessors
32
+ const std::set<SelectionBox>& get_boxes() const
33
+ {
34
+ return _boxes;
35
+ }
36
+ size_t count() const
37
+ {
38
+ return _boxes.size();
39
+ }
40
+ std::set<SelectionBox>::const_iterator begin() const
41
+ {
42
+ return _boxes.begin();
43
+ }
44
+ std::set<SelectionBox>::const_iterator end() const
45
+ {
46
+ return _boxes.end();
47
+ }
48
+
49
+ // Bounds
50
+ std::int64_t min_x() const;
51
+ std::int64_t min_y() const;
52
+ std::int64_t min_z() const;
53
+ std::int64_t max_x() const;
54
+ std::int64_t max_y() const;
55
+ std::int64_t max_z() const;
56
+ std::array<std::int64_t, 3> min() const;
57
+ std::array<std::int64_t, 3> max() const;
58
+ std::pair<
59
+ std::array<std::int64_t, 3>,
60
+ std::array<std::int64_t, 3>>
61
+ bounds() const;
62
+ SelectionBox bounding_box() const;
63
+
64
+ // Contains and intersects
65
+ bool contains_block(std::int64_t x, std::int64_t y, std::int64_t z) const;
66
+ bool contains_point(double x, double y, double z) const;
67
+ bool intersects(const SelectionBox& other) const;
68
+ bool intersects(const SelectionBoxGroup& other) const;
69
+
70
+ // Transform
71
+ SelectionBoxGroup translate(std::int64_t dx, std::int64_t dy, std::int64_t dz) const;
72
+ SelectionBoxGroup transform(const Matrix4x4&) const;
73
+
74
+ // Operators
75
+ operator bool() const
76
+ {
77
+ return !_boxes.empty();
78
+ }
79
+ std::strong_ordering operator<=>(const SelectionBoxGroup& other) const = default;
80
+ bool operator==(const SelectionBoxGroup& rhs) const = default;
81
+ bool operator!=(const SelectionBoxGroup& rhs) const = default;
82
+
83
+ operator std::set<SelectionBox>() const
84
+ {
85
+ return _boxes;
86
+ }
87
+ };
88
+
89
+ }