amulet-core 2.0a6__cp311-cp311-win_amd64.whl → 2.0a8__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.

Files changed (149) hide show
  1. amulet/__init__.cp311-win_amd64.pyd +0 -0
  2. amulet/__init__.py.cpp +6 -0
  3. amulet/__init__.pyi +2 -2
  4. amulet/_init.py +0 -2
  5. amulet/_version.py +3 -3
  6. amulet/biome.pyi +0 -2
  7. amulet/block.pyi +0 -2
  8. amulet/block_entity.pyi +0 -2
  9. amulet/chunk.hpp +2 -1
  10. amulet/chunk.pyi +0 -2
  11. amulet/chunk_components.pyi +20 -18
  12. amulet/collections/eq.py.hpp +1 -1
  13. amulet/collections/mapping.py.hpp +18 -11
  14. amulet/collections/mutable_mapping.py.hpp +17 -6
  15. amulet/collections/sequence.py.hpp +5 -6
  16. amulet/collections.pyi +8 -5
  17. amulet/entity.py +22 -20
  18. amulet/game/translate/_functions/_code_functions/_text.py +2 -2
  19. amulet/game/translate/_functions/abc.py +10 -3
  20. amulet/img/__init__.py +10 -0
  21. amulet/img/missing_no.png +0 -0
  22. amulet/img/missing_pack.png +0 -0
  23. amulet/level/__init__.pyi +2 -6
  24. amulet/level/abc/_chunk_handle.py +45 -22
  25. amulet/level/abc/_level/_creatable_level.py +1 -2
  26. amulet/level/abc/_level/_level.py +1 -5
  27. amulet/level/java/__init__.pyi +0 -5
  28. amulet/level/java/_raw/__init__.pyi +0 -4
  29. amulet/level/java/_raw/java_chunk_decode.cpp +2 -4
  30. amulet/level/java/long_array.pyi +2 -1
  31. amulet/mesh/block/__init__.pyi +301 -0
  32. amulet/mesh/block/_cube.py +198 -0
  33. amulet/mesh/block/_missing_block.py +20 -0
  34. amulet/mesh/block/block_mesh.cpp +107 -0
  35. amulet/mesh/block/block_mesh.hpp +207 -0
  36. amulet/mesh/util.py +17 -0
  37. amulet/player.py +4 -6
  38. amulet/pybind11/collections.hpp +80 -38
  39. amulet/pybind11/numpy.hpp +26 -0
  40. amulet/pybind11/py_module.hpp +16 -51
  41. amulet/pybind11/type_hints.hpp +51 -0
  42. amulet/pybind11/types.hpp +14 -6
  43. amulet/pybind11/typing.hpp +7 -0
  44. amulet/resource_pack/__init__.py +63 -0
  45. amulet/resource_pack/abc/__init__.py +2 -0
  46. amulet/resource_pack/abc/resource_pack.py +38 -0
  47. amulet/resource_pack/abc/resource_pack_manager.py +85 -0
  48. amulet/resource_pack/java/__init__.py +2 -0
  49. amulet/resource_pack/java/download_resources.py +212 -0
  50. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_black.png +0 -0
  51. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_blue.png +0 -0
  52. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_brown.png +0 -0
  53. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_cyan.png +0 -0
  54. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_gray.png +0 -0
  55. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_green.png +0 -0
  56. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_light_blue.png +0 -0
  57. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_light_gray.png +0 -0
  58. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_lime.png +0 -0
  59. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_magenta.png +0 -0
  60. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_orange.png +0 -0
  61. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_pink.png +0 -0
  62. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_purple.png +0 -0
  63. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_red.png +0 -0
  64. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_white.png +0 -0
  65. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/banner/banner_yellow.png +0 -0
  66. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/barrier.png +0 -0
  67. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/end_portal.png +0 -0
  68. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/grass.png +0 -0
  69. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/lava.png +0 -0
  70. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/structure_void.png +0 -0
  71. amulet/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water.png +0 -0
  72. amulet/resource_pack/java/java_vanilla_fix/pack.png +0 -0
  73. amulet/resource_pack/java/resource_pack.py +44 -0
  74. amulet/resource_pack/java/resource_pack_manager.py +563 -0
  75. amulet/resource_pack/unknown_resource_pack.py +10 -0
  76. amulet/utils/__init__.pyi +0 -5
  77. amulet/utils/call_spec/_call_spec.py +2 -7
  78. amulet/utils/cast.py +10 -0
  79. amulet/utils/comment_json.py +188 -0
  80. amulet/utils/matrix.py +3 -3
  81. amulet/utils/numpy_helpers.py +2 -2
  82. amulet/utils/shareable_lock.py +2 -2
  83. amulet/utils/world_utils.py +2 -2
  84. amulet/version.pyi +0 -8
  85. {amulet_core-2.0a6.dist-info → amulet_core-2.0a8.dist-info}/METADATA +2 -2
  86. {amulet_core-2.0a6.dist-info → amulet_core-2.0a8.dist-info}/RECORD +91 -103
  87. {amulet_core-2.0a6.dist-info → amulet_core-2.0a8.dist-info}/WHEEL +1 -1
  88. amulet/chunk_/components/biome.py +0 -155
  89. amulet/chunk_/components/block_entity.py +0 -117
  90. amulet/chunk_/components/entity.py +0 -64
  91. amulet/chunk_/components/height_2d.py +0 -16
  92. amulet/level/bedrock/__init__.py +0 -2
  93. amulet/level/bedrock/_chunk_handle.py +0 -19
  94. amulet/level/bedrock/_dimension.py +0 -22
  95. amulet/level/bedrock/_level.py +0 -187
  96. amulet/level/bedrock/_raw/__init__.py +0 -5
  97. amulet/level/bedrock/_raw/_actor_counter.py +0 -53
  98. amulet/level/bedrock/_raw/_chunk.py +0 -54
  99. amulet/level/bedrock/_raw/_chunk_decode.py +0 -668
  100. amulet/level/bedrock/_raw/_chunk_encode.py +0 -602
  101. amulet/level/bedrock/_raw/_constant.py +0 -9
  102. amulet/level/bedrock/_raw/_dimension.py +0 -343
  103. amulet/level/bedrock/_raw/_level.py +0 -463
  104. amulet/level/bedrock/_raw/_level_dat.py +0 -90
  105. amulet/level/bedrock/_raw/_typing.py +0 -6
  106. amulet/level/bedrock/_raw/leveldb_chunk_versions.py +0 -83
  107. amulet/level/bedrock/chunk/__init__.py +0 -1
  108. amulet/level/bedrock/chunk/_chunk.py +0 -126
  109. amulet/level/bedrock/chunk/components/chunk_version.py +0 -12
  110. amulet/level/bedrock/chunk/components/finalised_state.py +0 -13
  111. amulet/level/bedrock/chunk/components/raw_chunk.py +0 -15
  112. amulet/level/construction/__init__.py +0 -0
  113. amulet/level/java/_chunk_handle.pyi +0 -15
  114. amulet/level/java/_dimension.pyi +0 -13
  115. amulet/level/java/_level.pyi +0 -120
  116. amulet/level/java/_raw/_chunk_decode.py +0 -561
  117. amulet/level/java/_raw/_chunk_encode.py +0 -463
  118. amulet/level/java/_raw/_constant.pyi +0 -20
  119. amulet/level/java/_raw/_data_pack/__init__.pyi +0 -8
  120. amulet/level/java/_raw/_data_pack/data_pack.pyi +0 -197
  121. amulet/level/java/_raw/_data_pack/data_pack_manager.pyi +0 -75
  122. amulet/level/java/_raw/_dimension.pyi +0 -72
  123. amulet/level/java/_raw/_level.pyi +0 -238
  124. amulet/level/java/_raw/_typing.pyi +0 -5
  125. amulet/level/java/anvil/__init__.pyi +0 -11
  126. amulet/level/java/anvil/_dimension.pyi +0 -109
  127. amulet/level/java/anvil/_region.pyi +0 -197
  128. amulet/level/java/anvil/_sector_manager.pyi +0 -142
  129. amulet/level/java_forge/__init__.py +0 -0
  130. amulet/level/mcstructure/__init__.py +0 -0
  131. amulet/level/nbt/__init__.py +0 -0
  132. amulet/level/schematic/__init__.py +0 -0
  133. amulet/level/sponge_schematic/__init__.py +0 -0
  134. amulet/pybind11/python.hpp +0 -14
  135. amulet/utils/call_spec/__init__.pyi +0 -53
  136. amulet/utils/call_spec/_call_spec.pyi +0 -272
  137. amulet/utils/matrix.pyi +0 -177
  138. amulet/utils/shareable_lock.pyi +0 -190
  139. amulet/utils/signal/__init__.pyi +0 -25
  140. amulet/utils/signal/_signal.pyi +0 -84
  141. amulet/utils/task_manager.pyi +0 -168
  142. amulet/utils/typing.py +0 -4
  143. amulet/utils/typing.pyi +0 -6
  144. amulet/utils/weakref.pyi +0 -50
  145. amulet/utils/world_utils.pyi +0 -109
  146. /amulet/img/{missing_world_icon.png → missing_world.png} +0 -0
  147. /amulet/{level/bedrock/chunk/components → mesh}/__init__.py +0 -0
  148. {amulet_core-2.0a6.dist-info → amulet_core-2.0a8.dist-info}/entry_points.txt +0 -0
  149. {amulet_core-2.0a6.dist-info → amulet_core-2.0a8.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,198 @@
1
+ from typing import TypeAlias
2
+ import numpy
3
+ import itertools
4
+
5
+ from amulet.mesh.block import (
6
+ BlockMesh,
7
+ BlockMeshPart,
8
+ Triangle,
9
+ Vertex,
10
+ FloatVec3,
11
+ FloatVec2,
12
+ BlockMeshTransparency,
13
+ BlockMeshCullDirection,
14
+ )
15
+
16
+ BoundsType: TypeAlias = tuple[
17
+ tuple[float, float], tuple[float, float], tuple[float, float]
18
+ ]
19
+ TextureUVType: TypeAlias = tuple[
20
+ tuple[float, float, float, float],
21
+ tuple[float, float, float, float],
22
+ tuple[float, float, float, float],
23
+ tuple[float, float, float, float],
24
+ tuple[float, float, float, float],
25
+ tuple[float, float, float, float],
26
+ ]
27
+
28
+ UNIT_BOX_COORDINATES = numpy.array(
29
+ list(itertools.product((0, 1), (0, 1), (0, 1)))
30
+ ) # X, Y, Z
31
+
32
+ CULL_DIRECTION_NAMES = (
33
+ "down",
34
+ "up",
35
+ "north",
36
+ "east",
37
+ "south",
38
+ "west",
39
+ )
40
+
41
+ # This maps face direction to the vertices used (defined in UNIT_BOX_COORDINATES)
42
+ VERTEX_INDEXES = (
43
+ numpy.array([0, 4, 5, 1]),
44
+ numpy.array([3, 7, 6, 2]),
45
+ numpy.array([4, 0, 2, 6]),
46
+ numpy.array([5, 4, 6, 7]),
47
+ numpy.array([1, 5, 7, 3]),
48
+ numpy.array([0, 1, 3, 2]),
49
+ )
50
+
51
+ # This maps face direction to the vertices used (defined in UNIT_BOX_COORDINATES)
52
+ CUBE_FACE_LUT = dict(zip(CULL_DIRECTION_NAMES, VERTEX_INDEXES))
53
+
54
+ TRI_FACE = numpy.array([0, 1, 2, 0, 2, 3], numpy.uint32)
55
+
56
+ # cube_vert_lut = { # This maps from vertex index to index in [minx, miny, minz, maxx, maxy, maxz]
57
+ # 1: [0, 1, 5],
58
+ # 3: [0, 4, 5],
59
+ # 0: [0, 1, 2],
60
+ # 2: [0, 4, 2],
61
+ # 5: [3, 1, 5],
62
+ # 7: [3, 4, 5],
63
+ # 4: [3, 1, 2],
64
+ # 6: [3, 4, 2],
65
+ # }
66
+ #
67
+ # # combines the above two to map from face to index in [minx, miny, minz, maxx, maxy, maxz]. Used to index a numpy array
68
+ # # The above two have been kept separate because the merged result is unintuitive and difficult to edit.
69
+ # cube_lut = {
70
+ # face_dir_: [
71
+ # vert_coord_ for vert_ in vert_index_ for vert_coord_ in cube_vert_lut[vert_]
72
+ # ]
73
+ # for face_dir_, vert_index_ in CUBE_FACE_LUT.items()
74
+ # }
75
+
76
+ UV_ROTATION_LUT = [0, 3, 2, 3, 2, 1, 0, 1] # remap
77
+
78
+
79
+ # tvert_lut = { # TODO: implement this for the cases where the UV is not defined
80
+ # 'down': [],
81
+ # 'up': [],
82
+ # 'north': [],
83
+ # 'east': [],
84
+ # 'south': [],
85
+ # 'west': []
86
+ # }
87
+
88
+
89
+ def get_cube(
90
+ down: str,
91
+ up: str,
92
+ north: str,
93
+ east: str,
94
+ south: str,
95
+ west: str,
96
+ transparency: BlockMeshTransparency = BlockMeshTransparency.FullOpaque,
97
+ tint: tuple[int, int, int] = (1, 1, 1),
98
+ bounds: BoundsType = ((0, 1), (0, 1), (0, 1)),
99
+ texture_uv: TextureUVType = ((0, 0, 1, 1),) * 6,
100
+ do_not_cull: tuple[bool, bool, bool, bool, bool, bool] = (
101
+ False,
102
+ False,
103
+ False,
104
+ False,
105
+ False,
106
+ False,
107
+ ),
108
+ ) -> BlockMesh:
109
+ texture_paths: dict[str, int] = {}
110
+ mesh_parts: list[tuple[list[Vertex], list[Triangle]] | None] = [
111
+ None,
112
+ None,
113
+ None,
114
+ None,
115
+ None,
116
+ None,
117
+ None,
118
+ ]
119
+ box_coordinates = list(itertools.product(*bounds))
120
+ tint_vec = FloatVec3(*tint)
121
+
122
+ for (
123
+ cull_direction,
124
+ vertex_index,
125
+ do_not_cull_face,
126
+ texture_path,
127
+ texture_coords,
128
+ ) in zip(
129
+ (
130
+ BlockMeshCullDirection.CullDown,
131
+ BlockMeshCullDirection.CullUp,
132
+ BlockMeshCullDirection.CullNorth,
133
+ BlockMeshCullDirection.CullEast,
134
+ BlockMeshCullDirection.CullSouth,
135
+ BlockMeshCullDirection.CullWest,
136
+ ),
137
+ VERTEX_INDEXES,
138
+ do_not_cull,
139
+ (down, up, north, east, south, west),
140
+ texture_uv,
141
+ ):
142
+ # Get the index of the texture path. Add if it is not contained.
143
+ texture_index = texture_paths.setdefault(texture_path, len(texture_paths))
144
+ if do_not_cull_face:
145
+ cull_direction = BlockMeshCullDirection.CullNone
146
+ part = mesh_parts[cull_direction]
147
+ if part is None:
148
+ mesh_parts[cull_direction] = part = ([], [])
149
+ verts, tris = part
150
+ vert_count = len(verts)
151
+
152
+ for i in range(4):
153
+ x, y, z = box_coordinates[vertex_index[i]]
154
+ uvx = texture_coords[UV_ROTATION_LUT[i * 2]]
155
+ uvy = texture_coords[UV_ROTATION_LUT[i * 2 + 1]]
156
+ verts.append(
157
+ Vertex(
158
+ FloatVec3(x, y, z),
159
+ FloatVec2(uvx, uvy),
160
+ tint_vec,
161
+ )
162
+ )
163
+ for a, b, c in TRI_FACE.reshape((2, 3)):
164
+ tris.append(
165
+ Triangle(a + vert_count, b + vert_count, c + vert_count, texture_index)
166
+ )
167
+
168
+ def create_part(
169
+ part: tuple[list[Vertex], list[Triangle]] | None
170
+ ) -> BlockMeshPart | None:
171
+ return None if part is None else BlockMeshPart(*part)
172
+
173
+ return BlockMesh(
174
+ transparency,
175
+ list(texture_paths),
176
+ (
177
+ create_part(mesh_parts[0]),
178
+ create_part(mesh_parts[1]),
179
+ create_part(mesh_parts[2]),
180
+ create_part(mesh_parts[3]),
181
+ create_part(mesh_parts[4]),
182
+ create_part(mesh_parts[5]),
183
+ create_part(mesh_parts[6]),
184
+ ),
185
+ )
186
+
187
+
188
+ def get_unit_cube(
189
+ down: str,
190
+ up: str,
191
+ north: str,
192
+ east: str,
193
+ south: str,
194
+ west: str,
195
+ transparency: BlockMeshTransparency = BlockMeshTransparency.FullOpaque,
196
+ tint: tuple[int, int, int] = (1, 1, 1),
197
+ ) -> BlockMesh:
198
+ return get_cube(down, up, north, east, south, west, transparency, tint)
@@ -0,0 +1,20 @@
1
+ from __future__ import annotations
2
+ from typing import TYPE_CHECKING
3
+
4
+ from amulet.mesh.block import BlockMesh
5
+ from ._cube import get_unit_cube
6
+
7
+ if TYPE_CHECKING:
8
+ from amulet.resource_pack.abc import BaseResourcePackManager
9
+
10
+
11
+ def get_missing_block(resource_pack: BaseResourcePackManager) -> BlockMesh:
12
+ texture_path = resource_pack.get_texture_path("minecraft", "missing_no")
13
+ return get_unit_cube(
14
+ texture_path,
15
+ texture_path,
16
+ texture_path,
17
+ texture_path,
18
+ texture_path,
19
+ texture_path,
20
+ )
@@ -0,0 +1,107 @@
1
+ #include <string>
2
+ #include <array>
3
+ #include <functional>
4
+ #include "block_mesh.hpp"
5
+
6
+ namespace Amulet {
7
+
8
+ const std::array<BlockMeshCullDirection, 4> roty_map = { BlockMeshCullNorth, BlockMeshCullEast, BlockMeshCullSouth, BlockMeshCullWest };
9
+
10
+ const RotationCullMapType RotationCullMap = []() {
11
+ RotationCullMapType cull_map;
12
+ for (std::int8_t roty = -3; roty < 4; roty++) {
13
+ // Create the rotated Y array
14
+ std::array<BlockMeshCullDirection, 4> roty_map_rotated;
15
+ auto split_y_point = 0 <= roty ? roty : roty + roty_map.size();
16
+ std::copy(roty_map.begin() + split_y_point, roty_map.end(), roty_map_rotated.begin());
17
+ std::copy(roty_map.begin(), roty_map.begin() + split_y_point, roty_map_rotated.end() - split_y_point);
18
+ // Create the X array
19
+ const std::array<BlockMeshCullDirection, 4> rotx_map = { roty_map_rotated[0], BlockMeshCullDown, roty_map_rotated[2], BlockMeshCullUp };
20
+
21
+ for (std::int8_t rotx = -3; rotx < 4; rotx++) {
22
+ // Create the rotated X array
23
+ std::array<BlockMeshCullDirection, 4> rotx_map_rotated;
24
+ auto split_x_point = 0 <= rotx ? rotx : rotx + rotx_map.size();
25
+ std::copy(rotx_map.begin() + split_x_point, rotx_map.end(), rotx_map_rotated.begin());
26
+ std::copy(rotx_map.begin(), rotx_map.begin() + split_x_point, rotx_map_rotated.end() - split_x_point);
27
+
28
+ cull_map[std::make_pair(roty, rotx)] = {
29
+ BlockMeshCullNone,
30
+ rotx_map_rotated[3],
31
+ rotx_map_rotated[1],
32
+ rotx_map_rotated[0],
33
+ roty_map_rotated[1],
34
+ rotx_map_rotated[2],
35
+ roty_map_rotated[3]
36
+ };
37
+ }
38
+ }
39
+ return cull_map;
40
+ }();
41
+
42
+ BlockMesh merge_block_meshes(std::vector<std::reference_wrapper<const BlockMesh>> meshes) {
43
+ BlockMesh new_mesh;
44
+ new_mesh.transparency = BlockMeshTransparency::Partial;
45
+ std::map<std::string, size_t> texture_index_map;
46
+ for (const auto& wrapper : meshes) {
47
+ const auto& temp_mesh = wrapper.get();
48
+ // Get the minimum transparency of the two meshes.
49
+ new_mesh.transparency = std::min(new_mesh.transparency, temp_mesh.transparency);
50
+
51
+ // Copy over mesh parts
52
+ for (std::uint8_t cull_direction = 0; cull_direction < 7; cull_direction++) {
53
+ const auto& temp_mesh_part = temp_mesh.parts[cull_direction];
54
+ if (temp_mesh_part) {
55
+ auto& new_mesh_part = new_mesh.parts[cull_direction];
56
+ if (!new_mesh_part) {
57
+ // Initialise the mesh part if it is null.
58
+ new_mesh_part = BlockMeshPart();
59
+ }
60
+ // Get the number of triangles before copying
61
+ size_t vert_count = new_mesh_part->verts.size();
62
+ size_t triangle_count = new_mesh_part->triangles.size();
63
+
64
+ auto& new_verts = new_mesh_part->verts;
65
+ auto& temp_verts = temp_mesh_part->verts;
66
+ auto& new_triangles = new_mesh_part->triangles;
67
+ auto& temp_triangles = temp_mesh_part->triangles;
68
+
69
+ // Copy over vertices
70
+ new_verts.insert(
71
+ new_verts.end(),
72
+ temp_verts.begin(),
73
+ temp_verts.end());
74
+ // Copy over triangles
75
+ new_triangles.insert(
76
+ new_triangles.end(),
77
+ temp_triangles.begin(),
78
+ temp_triangles.end());
79
+
80
+ for (size_t i = triangle_count; i < new_mesh_part->triangles.size(); i++) {
81
+ // Update the triangle indexes
82
+ auto& triangle = new_mesh_part->triangles[i];
83
+ triangle.vert_index_a += vert_count;
84
+ triangle.vert_index_b += vert_count;
85
+ triangle.vert_index_c += vert_count;
86
+ if (temp_mesh.textures.size() <= triangle.texture_index) {
87
+ throw std::invalid_argument("Texture index is higher than the number of textures.");
88
+ }
89
+ const auto& texture_path = temp_mesh.textures[triangle.texture_index];
90
+ auto it = texture_index_map.find(texture_path);
91
+ if (it == texture_index_map.end()) {
92
+ // Texture has not been added yet.
93
+ size_t texture_index = new_mesh.textures.size();
94
+ new_mesh.textures.push_back(texture_path);
95
+ triangle.texture_index = texture_index;
96
+ texture_index_map[texture_path] = texture_index;
97
+ } else {
98
+ triangle.texture_index = it->second;
99
+ }
100
+ }
101
+ }
102
+ }
103
+ }
104
+ return new_mesh;
105
+ }
106
+
107
+ }
@@ -0,0 +1,207 @@
1
+ #pragma once
2
+ #include <array>
3
+ #include <cmath>
4
+ #include <map>
5
+ #include <numbers>
6
+ #include <optional>
7
+ #include <stdexcept>
8
+ #include <string>
9
+ #include <vector>
10
+ #include <functional>
11
+
12
+ namespace Amulet {
13
+
14
+ class FloatVec2 {
15
+ public:
16
+ float x;
17
+ float y;
18
+
19
+ FloatVec2(float x, float y)
20
+ : x(x)
21
+ , y(y)
22
+ {
23
+ }
24
+ };
25
+
26
+ class FloatVec3 {
27
+ public:
28
+ float x;
29
+ float y;
30
+ float z;
31
+
32
+ FloatVec3(float x, float y, float z)
33
+ : x(x)
34
+ , y(y)
35
+ , z(z)
36
+ {
37
+ }
38
+ };
39
+
40
+ class Vertex {
41
+ public:
42
+ // The world coordinate
43
+ FloatVec3 coord;
44
+ // The texture coordinate
45
+ FloatVec2 texture_coord;
46
+ // The tint colour
47
+ FloatVec3 tint;
48
+
49
+ Vertex(
50
+ const FloatVec3& coord,
51
+ const FloatVec2& texture_coord,
52
+ const FloatVec3& tint)
53
+ : coord(coord)
54
+ , texture_coord(texture_coord)
55
+ , tint(tint)
56
+ {
57
+ }
58
+ };
59
+
60
+ class Triangle {
61
+ public:
62
+ // The indicies of the vertexes in BlockMeshPart::verts.
63
+ size_t vert_index_a;
64
+ size_t vert_index_b;
65
+ size_t vert_index_c;
66
+ // The index of the texture in BlockMesh::textures.
67
+ size_t texture_index;
68
+
69
+ Triangle(
70
+ size_t vert_index_a,
71
+ size_t vert_index_b,
72
+ size_t vert_index_c,
73
+ size_t texture_index)
74
+ : vert_index_a(vert_index_a)
75
+ , vert_index_b(vert_index_b)
76
+ , vert_index_c(vert_index_c)
77
+ , texture_index(texture_index)
78
+ {
79
+ }
80
+ };
81
+
82
+ class BlockMeshPart {
83
+ public:
84
+ // The vertices in this mesh part.
85
+ std::vector<Vertex> verts;
86
+ // The triangles in this mesh part.
87
+ std::vector<Triangle> triangles;
88
+
89
+ BlockMeshPart(): verts(), triangles() {}
90
+ BlockMeshPart(
91
+ const std::vector<Vertex>& verts,
92
+ const std::vector<Triangle>& triangles)
93
+ : verts(verts)
94
+ , triangles(triangles)
95
+ {
96
+ }
97
+ };
98
+
99
+ enum class BlockMeshTransparency : std::uint8_t {
100
+ // The block is a full block with opaque textures
101
+ FullOpaque,
102
+ // The block is a full block with transparent / translucent textures
103
+ FullTranslucent,
104
+ // The block is not a full block
105
+ Partial
106
+ };
107
+
108
+ enum BlockMeshCullDirection {
109
+ BlockMeshCullNone,
110
+ BlockMeshCullUp,
111
+ BlockMeshCullDown,
112
+ BlockMeshCullNorth,
113
+ BlockMeshCullEast,
114
+ BlockMeshCullSouth,
115
+ BlockMeshCullWest
116
+ };
117
+
118
+ typedef std::map<
119
+ std::pair<std::int8_t, std::int8_t>,
120
+ std::array<BlockMeshCullDirection, 7>>
121
+ RotationCullMapType;
122
+
123
+ // For every combination of 90 degree rotations in y and x axis
124
+ // gives the rotated cull direction.
125
+ extern const RotationCullMapType RotationCullMap;
126
+
127
+ class BlockMesh {
128
+ public:
129
+ BlockMeshTransparency transparency;
130
+ std::vector<std::string> textures;
131
+ // The mesh parts. Index matches BlockMeshCullDirection.
132
+ std::array<std::optional<BlockMeshPart>, 7> parts;
133
+
134
+ BlockMesh()
135
+ : transparency()
136
+ , textures()
137
+ , parts()
138
+ {
139
+ }
140
+ BlockMesh(
141
+ BlockMeshTransparency transparency,
142
+ const std::vector<std::string>& textures,
143
+ const std::array<std::optional<BlockMeshPart>, 7>& parts)
144
+ : transparency(transparency)
145
+ , textures(textures)
146
+ , parts(parts)
147
+ {
148
+ }
149
+
150
+ BlockMesh rotate(std::int8_t rotx, std::int8_t roty) const
151
+ {
152
+ if (rotx || roty) {
153
+ auto rotation_key = std::make_pair(rotx, roty);
154
+ auto it = RotationCullMap.find(rotation_key);
155
+ if (it != RotationCullMap.end()) {
156
+ const auto& cull_map = it->second;
157
+ BlockMesh mesh;
158
+ mesh.transparency = transparency;
159
+ mesh.textures = textures;
160
+
161
+ // Compuate rotation values
162
+ float theta_x = std::numbers::pi * rotx / 2.0;
163
+ float theta_y = std::numbers::pi * roty / 2.0;
164
+ float sin_x = std::sin(theta_x);
165
+ float cos_x = std::cos(theta_x);
166
+ float sin_y = std::sin(theta_y);
167
+ float cos_y = std::cos(theta_y);
168
+
169
+ for (std::uint8_t cull_direction = 0; cull_direction < 7; cull_direction++) {
170
+ // Copy the part to the new cull direction.
171
+ auto new_cull_direction = cull_map[cull_direction];
172
+ auto& part = mesh.parts[new_cull_direction] = parts[cull_direction];
173
+
174
+ if (part) {
175
+ // Rotate the vertex coords.
176
+ for (auto& vertex : part->verts) {
177
+ auto& coord = vertex.coord;
178
+ float x = coord.x - 0.5;
179
+ float y = coord.y - 0.5;
180
+ float z = coord.z - 0.5;
181
+
182
+ // Rotate in X axis
183
+ float y_ = y * cos_x - z * sin_x;
184
+ z = y * sin_x + z * cos_x;
185
+ y = y_;
186
+
187
+ // Rotate in Y axis
188
+ float x_ = x * cos_y + z * sin_y;
189
+ z = -x * sin_y + z * cos_y;
190
+ x = x_;
191
+
192
+ coord.x = x + 0.5;
193
+ coord.y = y + 0.5;
194
+ coord.z = z + 0.5;
195
+ }
196
+ }
197
+ }
198
+ return mesh;
199
+ }
200
+ }
201
+ return *this;
202
+ }
203
+ };
204
+
205
+ BlockMesh merge_block_meshes(std::vector<std::reference_wrapper<const BlockMesh>>);
206
+
207
+ }
amulet/mesh/util.py ADDED
@@ -0,0 +1,17 @@
1
+ import numpy
2
+
3
+
4
+ def rotate_3d(
5
+ verts: numpy.ndarray, x: float, y: float, z: float, dx: float, dy: float, dz: float
6
+ ) -> numpy.ndarray:
7
+ sb, sh, sa = numpy.sin(numpy.radians([x, y, z]))
8
+ cb, ch, ca = numpy.cos(numpy.radians([x, y, z]))
9
+ trmtx = numpy.array(
10
+ [
11
+ [ch * ca, -ch * sa * cb + sh * sb, ch * sa * sb + sh * cb],
12
+ [sa, ca * cb, -ca * sb],
13
+ [-sh * ca, sh * sa * cb + ch * sb, -sh * sa * sb + ch * cb],
14
+ ]
15
+ )
16
+ origin = numpy.array([dx, dy, dz])
17
+ return numpy.matmul(verts - origin, trmtx) + origin # type: ignore
amulet/player.py CHANGED
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Tuple
4
-
5
3
  from amulet.data_types import DimensionId
6
4
 
7
5
  LOCAL_PLAYER = "~local_player"
@@ -12,8 +10,8 @@ class Player:
12
10
  self,
13
11
  player_id: str,
14
12
  dimension_id: DimensionId,
15
- location: Tuple[float, float, float],
16
- rotation: Tuple[float, float],
13
+ location: tuple[float, float, float],
14
+ rotation: tuple[float, float],
17
15
  ) -> None:
18
16
  """
19
17
  Creates a new instance of :class:`Player` with the given UUID, location, and rotation
@@ -49,12 +47,12 @@ class Player:
49
47
  return self._player_id
50
48
 
51
49
  @property
52
- def location(self) -> Tuple[float, float, float]:
50
+ def location(self) -> tuple[float, float, float]:
53
51
  """The current location of the player in the world"""
54
52
  return self._location
55
53
 
56
54
  @property
57
- def rotation(self) -> Tuple[float, float]:
55
+ def rotation(self) -> tuple[float, float]:
58
56
  """The current rotation of the player in the world"""
59
57
  return self._rotation
60
58