amulet-core 2.0a5__cp311-cp311-win_amd64.whl → 2.0a6__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 +39 -0
- amulet/_version.py +3 -3
- amulet/biome.py.cpp +122 -0
- amulet/block.py.cpp +377 -0
- amulet/block_entity.py.cpp +115 -0
- amulet/chunk.py.cpp +80 -0
- 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/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 +192 -0
- amulet/collections/mutable_mapping.py.hpp +215 -0
- amulet/collections/sequence.py.hpp +164 -0
- amulet/img/missing_world_icon.png +0 -0
- amulet/io/binary_reader.hpp +45 -0
- amulet/io/binary_writer.hpp +30 -0
- amulet/level/java/_raw/java_chunk_decode.cpp +533 -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/palette/biome_palette.hpp +85 -0
- amulet/palette/block_palette.cpp +32 -0
- amulet/palette/block_palette.hpp +93 -0
- amulet/pybind11/collections.hpp +76 -0
- amulet/pybind11/py_module.hpp +69 -0
- amulet/pybind11/python.hpp +14 -0
- amulet/pybind11/types.hpp +17 -0
- amulet/utils/numpy.hpp +36 -0
- amulet/version.py.cpp +281 -0
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a6.dist-info}/METADATA +2 -2
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a6.dist-info}/RECORD +50 -7
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a6.dist-info}/WHEEL +0 -0
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a6.dist-info}/entry_points.txt +0 -0
- {amulet_core-2.0a5.dist-info → amulet_core-2.0a6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
#include <memory>
|
|
2
|
+
#include <map>
|
|
3
|
+
#include <cstdint>
|
|
4
|
+
#include <stdexcept>
|
|
5
|
+
#include <type_traits>
|
|
6
|
+
#include <string>
|
|
7
|
+
#include <functional>
|
|
8
|
+
#include <variant>
|
|
9
|
+
#include <algorithm>
|
|
10
|
+
|
|
11
|
+
#include <pybind11/pybind11.h>
|
|
12
|
+
|
|
13
|
+
#include <amulet/pybind11/python.hpp>
|
|
14
|
+
|
|
15
|
+
#include <amulet_nbt/tag/named_tag.hpp>
|
|
16
|
+
#include <amulet_nbt/tag/compound.hpp>
|
|
17
|
+
|
|
18
|
+
#include <amulet/version.hpp>
|
|
19
|
+
#include <amulet/block.hpp>
|
|
20
|
+
#include <amulet/chunk.hpp>
|
|
21
|
+
#include <amulet/level/java/java_chunk.hpp>
|
|
22
|
+
#include <amulet/level/java/long_array.hpp>
|
|
23
|
+
|
|
24
|
+
namespace py = pybind11;
|
|
25
|
+
using namespace AmuletNBT;
|
|
26
|
+
|
|
27
|
+
namespace Amulet {
|
|
28
|
+
template <typename tagT>
|
|
29
|
+
tagT get_tag(const CompoundTag& compound, std::string name, std::function<tagT()> get_default) {
|
|
30
|
+
const auto& it = compound.find(name);
|
|
31
|
+
if (
|
|
32
|
+
it != compound.end() &&
|
|
33
|
+
std::holds_alternative<tagT>(it->second)
|
|
34
|
+
) {
|
|
35
|
+
return std::get<tagT>(it->second);
|
|
36
|
+
}
|
|
37
|
+
return get_default();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
template <typename tagT>
|
|
41
|
+
tagT pop_tag(CompoundTag& compound, std::string name, std::function<tagT()> get_default) {
|
|
42
|
+
auto node = compound.extract(name);
|
|
43
|
+
if (
|
|
44
|
+
node &&
|
|
45
|
+
std::holds_alternative<tagT>(node.mapped())
|
|
46
|
+
) {
|
|
47
|
+
return std::get<tagT>(node.mapped());
|
|
48
|
+
}
|
|
49
|
+
return get_default();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
CompoundTagPtr get_region(const std::map<std::string, NamedTag>& raw_chunk) {
|
|
53
|
+
const auto& it = raw_chunk.find("region");
|
|
54
|
+
if (
|
|
55
|
+
it != raw_chunk.end() &&
|
|
56
|
+
std::holds_alternative<CompoundTagPtr>(it->second.tag_node)
|
|
57
|
+
) {
|
|
58
|
+
return std::get<CompoundTagPtr>(it->second.tag_node);
|
|
59
|
+
}
|
|
60
|
+
return std::make_shared<CompoundTag>();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
CompoundTagPtr get_level(const CompoundTag& region) {
|
|
64
|
+
return get_tag<CompoundTagPtr>(
|
|
65
|
+
region,
|
|
66
|
+
"Level",
|
|
67
|
+
[]() { return std::make_shared<CompoundTag>(); }
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
std::int64_t validate_coords(
|
|
72
|
+
CompoundTag& level,
|
|
73
|
+
std::int64_t cx,
|
|
74
|
+
std::int64_t cz
|
|
75
|
+
) {
|
|
76
|
+
if (
|
|
77
|
+
pop_tag<IntTag>(level, "xPos", []() { return IntTag(); }).value != cx ||
|
|
78
|
+
pop_tag<IntTag>(level, "zPos", []() { return IntTag(); }).value != cz
|
|
79
|
+
) {
|
|
80
|
+
throw std::runtime_error("Chunk coord data is incorrect.");
|
|
81
|
+
}
|
|
82
|
+
std::int64_t cy = pop_tag<IntTag>(level, "yPos", []() { return IntTag(); }).value;
|
|
83
|
+
return cy << 4;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
template <typename chunkT>
|
|
87
|
+
void decode_last_update(chunkT& chunk, CompoundTag& level) {
|
|
88
|
+
// TODO
|
|
89
|
+
//pop_tag<LongTag>(level, "LastUpdate", []() { return LongTag(); }).value;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
template <typename chunkT>
|
|
93
|
+
void decode_inhabited_time(chunkT& chunk, CompoundTag& level) {
|
|
94
|
+
// TODO
|
|
95
|
+
//pop_tag<LongTag>(level, "InhabitedTime", []() { return LongTag(); }).value;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
template <typename chunkT>
|
|
99
|
+
void decode_terrain_populated(chunkT& chunk, CompoundTag& level) {
|
|
100
|
+
// TODO
|
|
101
|
+
//pop_tag<ByteTag>(level, "TerrainPopulated", []() { return ByteTag(1); }).value;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
template <typename chunkT>
|
|
105
|
+
void decode_light_populated(chunkT& chunk, CompoundTag& level) {
|
|
106
|
+
// TODO
|
|
107
|
+
//pop_tag<ByteTag>(level, "LightPopulated", []() { return ByteTag(1); }).value;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
template <typename chunkT>
|
|
111
|
+
void decode_status(chunkT& chunk, CompoundTag& level, std::int64_t data_version) {
|
|
112
|
+
// TODO
|
|
113
|
+
/*std::string status = pop_tag<StringTag>(level, "Status", []() { return StringTag(); });
|
|
114
|
+
if (!status.empty()) {
|
|
115
|
+
chunk.set_status(status);
|
|
116
|
+
}
|
|
117
|
+
else if (data_version >= 3454) {
|
|
118
|
+
chunk.set_status("minecraft:full");
|
|
119
|
+
}
|
|
120
|
+
else if (data_version >= 1912) {
|
|
121
|
+
chunk.set_status("full");
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
chunk.set_status("postprocessed");
|
|
125
|
+
}*/
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
template <typename chunkT>
|
|
129
|
+
void decode_heightmap(chunkT& chunk, CompoundTag& level) {
|
|
130
|
+
// TODO
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
template <typename chunkT>
|
|
134
|
+
void decode_heightmaps_compound(chunkT& chunk, CompoundTag& level) {
|
|
135
|
+
// TODO
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
template <int DataVersion>
|
|
139
|
+
std::shared_ptr<JavaChunk> _decode_java_chunk(
|
|
140
|
+
py::object game_version,
|
|
141
|
+
std::map<std::string, NamedTag>& raw_chunk,
|
|
142
|
+
CompoundTag& region,
|
|
143
|
+
std::int64_t cx,
|
|
144
|
+
std::int64_t cz,
|
|
145
|
+
std::shared_ptr<VersionNumber> version,
|
|
146
|
+
std::int64_t data_version,
|
|
147
|
+
std::shared_ptr<BlockStack> default_block,
|
|
148
|
+
std::shared_ptr<Biome> default_biome,
|
|
149
|
+
std::function<std::shared_ptr<Block>()> get_water
|
|
150
|
+
) {
|
|
151
|
+
// Validate coordinates
|
|
152
|
+
CompoundTagPtr level_ptr;
|
|
153
|
+
CompoundTag& level = [&]() -> CompoundTag& {
|
|
154
|
+
if constexpr (DataVersion >= 2203) {
|
|
155
|
+
return data_version >= 2844 ? region : *(level_ptr = get_level(region));
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
level_ptr = get_level(region);
|
|
159
|
+
return *level_ptr;
|
|
160
|
+
|
|
161
|
+
}
|
|
162
|
+
}();
|
|
163
|
+
auto floor_y = validate_coords(level, cx, cz);
|
|
164
|
+
|
|
165
|
+
// Make the chunk
|
|
166
|
+
auto chunk_ptr = [&]() {
|
|
167
|
+
if constexpr (DataVersion >= 2203) {
|
|
168
|
+
return std::make_shared<JavaChunk2203>(
|
|
169
|
+
data_version,
|
|
170
|
+
default_block,
|
|
171
|
+
default_biome
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
else if constexpr (DataVersion >= 1466) {
|
|
175
|
+
return std::make_shared<JavaChunk1466>(
|
|
176
|
+
data_version,
|
|
177
|
+
default_block,
|
|
178
|
+
default_biome
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
else if constexpr (DataVersion >= 1444) {
|
|
182
|
+
return std::make_shared<JavaChunk1444>(
|
|
183
|
+
data_version,
|
|
184
|
+
default_block,
|
|
185
|
+
default_biome
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
else if constexpr (DataVersion >= 0) {
|
|
189
|
+
return std::make_shared<JavaChunk0>(
|
|
190
|
+
data_version,
|
|
191
|
+
default_block,
|
|
192
|
+
default_biome
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
return std::make_shared<JavaChunkNA>(
|
|
197
|
+
default_block,
|
|
198
|
+
default_biome
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
}();
|
|
202
|
+
auto& chunk = *chunk_ptr;
|
|
203
|
+
|
|
204
|
+
if constexpr (DataVersion == -1) {
|
|
205
|
+
// LegacyVersionComponent TODO
|
|
206
|
+
//pop_tag<ByteTag>(*level, "V", []() { return ByteTag(1); });
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
decode_last_update(chunk, level);
|
|
210
|
+
decode_inhabited_time(chunk, level);
|
|
211
|
+
|
|
212
|
+
// Status
|
|
213
|
+
if constexpr (DataVersion >= 1444) {
|
|
214
|
+
decode_status(chunk, level, data_version);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
decode_terrain_populated(chunk, level);
|
|
218
|
+
decode_light_populated(chunk, level);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Heightmaps
|
|
222
|
+
if constexpr (DataVersion >= 1466) {
|
|
223
|
+
decode_heightmaps_compound(chunk, level);
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
decode_heightmap(chunk, level);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Sections
|
|
230
|
+
ListTagPtr sections_ptr = get_tag<ListTagPtr>(level, "sections", []() { return std::make_shared<ListTag>(); });
|
|
231
|
+
if (!std::holds_alternative<CompoundListTag>(*sections_ptr)) {
|
|
232
|
+
throw std::invalid_argument("Chunk sections is not a list of compound tags.");
|
|
233
|
+
}
|
|
234
|
+
auto& sections = std::get<CompoundListTag>(*sections_ptr);
|
|
235
|
+
std::map<std::int64_t, CompoundTagPtr> sections_map;
|
|
236
|
+
for (auto& tag : sections) {
|
|
237
|
+
sections_map.emplace(
|
|
238
|
+
get_tag<ByteTag>(*tag, "Y", []() { return ByteTag(); }).value,
|
|
239
|
+
tag
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// blocks
|
|
244
|
+
auto block_component = chunk.get_block();
|
|
245
|
+
auto block_palette = block_component->get_palette();
|
|
246
|
+
auto block_sections = block_component->get_sections();
|
|
247
|
+
if constexpr (DataVersion >= 1444) {
|
|
248
|
+
// Palette format
|
|
249
|
+
// if data_version >= 2844:
|
|
250
|
+
// region.sections[].block_states.data
|
|
251
|
+
// region.sections[].block_states.palette
|
|
252
|
+
// elif data_version >= 2836:
|
|
253
|
+
// region.Level.Sections[].block_states.data
|
|
254
|
+
// region.Level.Sections[].block_states.palette
|
|
255
|
+
// else:
|
|
256
|
+
// region.Level.Sections[].BlockStates
|
|
257
|
+
// region.Level.Sections[].Palette
|
|
258
|
+
|
|
259
|
+
// TODO: move this to C++
|
|
260
|
+
py::object Waterloggable = py::module::import("amulet.game.java").attr("Waterloggable");
|
|
261
|
+
py::object WaterloggableYes = Waterloggable.attr("Yes");
|
|
262
|
+
py::object WaterloggableAlways = Waterloggable.attr("Always");
|
|
263
|
+
|
|
264
|
+
for (auto& [cy, section] : sections_map) {
|
|
265
|
+
auto [palette_tag, data_tag] = [&]() {
|
|
266
|
+
if (data_version >= 2836) {
|
|
267
|
+
auto block_states_tag = pop_tag<CompoundTagPtr>(*section, "block_states", []() { return std::make_shared<CompoundTag>(); });
|
|
268
|
+
return std::make_pair(
|
|
269
|
+
pop_tag<ListTagPtr>(*block_states_tag, "palette", []() { return std::make_shared<ListTag>(); }),
|
|
270
|
+
pop_tag<LongArrayTagPtr>(*block_states_tag, "data", []() { return std::make_shared<LongArrayTag>(); })
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
return std::make_pair(
|
|
275
|
+
pop_tag<ListTagPtr>(*section, "Palette", []() { return std::make_shared<ListTag>(); }),
|
|
276
|
+
pop_tag<LongArrayTagPtr>(*section, "BlockStates", []() { return std::make_shared<LongArrayTag>(); })
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
}();
|
|
280
|
+
if (!std::holds_alternative<CompoundListTag>(*palette_tag)) { continue; }
|
|
281
|
+
const auto& palette = std::get<CompoundListTag>(*palette_tag);
|
|
282
|
+
size_t palette_size = palette.size();
|
|
283
|
+
std::vector<std::uint32_t> lut;
|
|
284
|
+
lut.reserve(palette_size);
|
|
285
|
+
for (auto& block_tag : palette) {
|
|
286
|
+
auto block_name = get_tag<StringTag>(*block_tag, "Name", []() -> StringTag { throw std::invalid_argument("Block has no Name attribute."); });
|
|
287
|
+
auto colon_index = block_name.find(':');
|
|
288
|
+
auto [block_namespace, block_base_name] = [&]() -> std::pair<std::string, std::string> {
|
|
289
|
+
if (colon_index == std::string::npos) {
|
|
290
|
+
return std::make_pair("", block_name);
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
return std::make_pair(
|
|
294
|
+
block_name.substr(0, colon_index),
|
|
295
|
+
block_name.substr(colon_index + 1)
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
}();
|
|
299
|
+
auto properties_tag = get_tag<CompoundTagPtr>(*block_tag, "Properties", []() { return std::make_shared<CompoundTag>(); });
|
|
300
|
+
std::map<std::string, PropertyValueType> block_properties;
|
|
301
|
+
for (const auto& [k, v] : *properties_tag) {
|
|
302
|
+
std::visit([&block_properties, &k](auto&& arg) {
|
|
303
|
+
using T = std::decay_t<decltype(arg)>;
|
|
304
|
+
if constexpr (
|
|
305
|
+
std::is_same_v<T, AmuletNBT::ByteTag> ||
|
|
306
|
+
std::is_same_v<T, AmuletNBT::ShortTag> ||
|
|
307
|
+
std::is_same_v<T, AmuletNBT::IntTag> ||
|
|
308
|
+
std::is_same_v<T, AmuletNBT::LongTag> ||
|
|
309
|
+
std::is_same_v<T, AmuletNBT::StringTag>
|
|
310
|
+
) {
|
|
311
|
+
block_properties.emplace(k, arg);
|
|
312
|
+
}
|
|
313
|
+
}, v);
|
|
314
|
+
}
|
|
315
|
+
std::vector<std::shared_ptr<Block>> blocks;
|
|
316
|
+
|
|
317
|
+
// TODO: convert this to C++
|
|
318
|
+
py::object waterloggable = game_version.attr("block").attr("waterloggable")(block_namespace, block_base_name);
|
|
319
|
+
if (py::equals(waterloggable, WaterloggableYes)) {
|
|
320
|
+
auto waterlogged_it = block_properties.find("waterlogged");
|
|
321
|
+
if (
|
|
322
|
+
waterlogged_it != block_properties.end() and
|
|
323
|
+
std::holds_alternative<StringTag>(waterlogged_it->second)
|
|
324
|
+
) {
|
|
325
|
+
if (std::get<StringTag>(waterlogged_it->second) == "true") {
|
|
326
|
+
blocks.push_back(get_water());
|
|
327
|
+
}
|
|
328
|
+
block_properties.erase(waterlogged_it);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
else if (py::equals(waterloggable, WaterloggableAlways)) {
|
|
332
|
+
blocks.push_back(get_water());
|
|
333
|
+
}
|
|
334
|
+
blocks.insert(
|
|
335
|
+
blocks.begin(),
|
|
336
|
+
std::make_shared<Block>(
|
|
337
|
+
"java",
|
|
338
|
+
version,
|
|
339
|
+
block_namespace,
|
|
340
|
+
block_base_name,
|
|
341
|
+
block_properties
|
|
342
|
+
)
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
lut.push_back(
|
|
346
|
+
block_palette->block_stack_to_index(
|
|
347
|
+
std::make_shared<BlockStack>(blocks)
|
|
348
|
+
)
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
block_sections->set_section(
|
|
353
|
+
cy,
|
|
354
|
+
[&] {
|
|
355
|
+
if (data_tag->empty()) {
|
|
356
|
+
return std::make_shared<IndexArray3D>(
|
|
357
|
+
std::make_tuple<std::uint16_t>(16, 16, 16),
|
|
358
|
+
0
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
std::vector<std::uint32_t> decoded_vector(4096);
|
|
363
|
+
std::span<std::uint32_t> decoded_span(decoded_vector);
|
|
364
|
+
Amulet::decode_long_array(
|
|
365
|
+
std::span<std::uint64_t>(reinterpret_cast<std::uint64_t*>(data_tag->data()), data_tag->size()),
|
|
366
|
+
decoded_span,
|
|
367
|
+
std::max<std::uint8_t>(4, std::bit_width(palette_size - 1)),
|
|
368
|
+
data_version <= 2529
|
|
369
|
+
);
|
|
370
|
+
auto index_array = std::make_shared<IndexArray3D>(
|
|
371
|
+
std::make_tuple<std::uint16_t>(16, 16, 16)
|
|
372
|
+
);
|
|
373
|
+
std::span<std::uint32_t> index_array_span(index_array->get_buffer(), index_array->get_size());
|
|
374
|
+
// Convert YZX to XYZ and look up in lut.
|
|
375
|
+
for (size_t y = 0; y < 16; y++) {
|
|
376
|
+
for (size_t x = 0; x < 16; x++) {
|
|
377
|
+
for (size_t z = 0; z < 16; z++) {
|
|
378
|
+
auto& block_index = decoded_span[y * 256 + z * 16 + x];
|
|
379
|
+
if (palette_size <= block_index) {
|
|
380
|
+
throw std::runtime_error(
|
|
381
|
+
"Block index at cx=" + std::to_string(cx) +
|
|
382
|
+
",cy=" + std::to_string(cy) +
|
|
383
|
+
",cz=" + std::to_string(cx) +
|
|
384
|
+
",dx=" + std::to_string(x) +
|
|
385
|
+
",dy=" + std::to_string(y) +
|
|
386
|
+
",dz=" + std::to_string(z) +
|
|
387
|
+
" is larger than the block palette size."
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
index_array_span[x * 256 + y * 16 + z] = lut[block_index];
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return index_array;
|
|
395
|
+
}
|
|
396
|
+
}()
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
// Numerical format
|
|
402
|
+
throw std::runtime_error("NotImplemented");
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// TODO: biomes
|
|
406
|
+
|
|
407
|
+
// Return the chunk
|
|
408
|
+
return chunk_ptr;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
// Get the default block for this dimension and version via the python API.
|
|
413
|
+
std::shared_ptr<BlockStack> get_default_block(
|
|
414
|
+
py::object dimension,
|
|
415
|
+
const VersionRange& version_range
|
|
416
|
+
) {
|
|
417
|
+
auto default_block = dimension.attr("default_block")().cast<std::shared_ptr<BlockStack>>();
|
|
418
|
+
std::vector<std::shared_ptr<Block>> blocks;
|
|
419
|
+
for (const auto& block : default_block->get_blocks()) {
|
|
420
|
+
if (version_range.contains(block->get_platform(), *block->get_version())) {
|
|
421
|
+
blocks.push_back(block);
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
py::object block_ = py::module::import("amulet.game").attr("get_game_version")(
|
|
425
|
+
py::cast(block->get_platform()),
|
|
426
|
+
py::cast(block->get_version())
|
|
427
|
+
).attr("block").attr("translate")(
|
|
428
|
+
"java",
|
|
429
|
+
py::cast(version_range.get_max_version()),
|
|
430
|
+
py::cast(block)
|
|
431
|
+
).attr("__getitem__")(0);
|
|
432
|
+
if (py::isinstance<Block>(block_)) {
|
|
433
|
+
blocks.push_back(block_.cast<std::shared_ptr<Block>>());
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
if (blocks.empty()) {
|
|
438
|
+
blocks.push_back(
|
|
439
|
+
std::make_shared<Block>(
|
|
440
|
+
version_range.get_platform(),
|
|
441
|
+
version_range.get_max_version(),
|
|
442
|
+
"minecraft",
|
|
443
|
+
"air"
|
|
444
|
+
)
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
return std::make_shared<BlockStack>(blocks);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
std::shared_ptr<Biome> get_default_biome(
|
|
451
|
+
py::object dimension,
|
|
452
|
+
const VersionRange& version_range
|
|
453
|
+
) {
|
|
454
|
+
auto biome = dimension.attr("default_biome")().cast<std::shared_ptr<Biome>>();
|
|
455
|
+
if (version_range.contains(biome->get_platform(), *biome->get_version())) {
|
|
456
|
+
return biome;
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
return py::module::import("amulet.game").attr("get_game_version")(
|
|
460
|
+
py::cast(biome->get_platform()),
|
|
461
|
+
py::cast(biome->get_version())
|
|
462
|
+
).attr("biome").attr("translate")(
|
|
463
|
+
"java",
|
|
464
|
+
py::cast(version_range.get_max_version()),
|
|
465
|
+
py::cast(biome)
|
|
466
|
+
).cast<std::shared_ptr<Biome>>();
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
std::shared_ptr<JavaChunk> decode_java_chunk(
|
|
471
|
+
py::object raw_level,
|
|
472
|
+
py::object dimension,
|
|
473
|
+
std::map<std::string, NamedTag>& raw_chunk,
|
|
474
|
+
std::int64_t cx,
|
|
475
|
+
std::int64_t cz
|
|
476
|
+
) {
|
|
477
|
+
// Get the region compound tag
|
|
478
|
+
CompoundTagPtr region = get_region(raw_chunk);
|
|
479
|
+
|
|
480
|
+
std::int64_t data_version = pop_tag<IntTag>(
|
|
481
|
+
*region,
|
|
482
|
+
"DataVersion",
|
|
483
|
+
[]() { return IntTag(-1); }
|
|
484
|
+
).value;
|
|
485
|
+
|
|
486
|
+
auto version = std::make_shared<VersionNumber>(std::initializer_list<std::int64_t>{ data_version });
|
|
487
|
+
auto version_range = std::make_shared<VersionRange>("java", version, version);
|
|
488
|
+
auto default_block = get_default_block(dimension, *version_range);
|
|
489
|
+
auto default_biome = get_default_biome(dimension, *version_range);
|
|
490
|
+
py::object game_version = py::module::import("amulet.game").attr("get_game_version")("java", py::cast(version));
|
|
491
|
+
|
|
492
|
+
std::shared_ptr<Block> _water_block;
|
|
493
|
+
auto get_water = [&version, &_water_block]() {
|
|
494
|
+
if (!_water_block) {
|
|
495
|
+
py::object block = py::module::import("amulet.game").attr("get_game_version")(
|
|
496
|
+
"java",
|
|
497
|
+
VersionNumber({ 3837 })
|
|
498
|
+
).attr("block").attr("translate")(
|
|
499
|
+
"java",
|
|
500
|
+
version,
|
|
501
|
+
Block(
|
|
502
|
+
"java",
|
|
503
|
+
VersionNumber({ 3837 }),
|
|
504
|
+
"minecraft",
|
|
505
|
+
"water",
|
|
506
|
+
std::initializer_list<BlockProperites::value_type>{ {"level", StringTag("0")} }
|
|
507
|
+
)
|
|
508
|
+
).attr("__getitem__")(0);
|
|
509
|
+
if (!py::isinstance<Block>(block)) {
|
|
510
|
+
throw std::runtime_error("Water block did not convert to a block in version Java " + version->toString());
|
|
511
|
+
}
|
|
512
|
+
_water_block = block.cast<std::shared_ptr<Block>>();
|
|
513
|
+
}
|
|
514
|
+
return _water_block;
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
if (data_version >= 2203) {
|
|
518
|
+
return _decode_java_chunk<2203>(game_version, raw_chunk, *region, cx, cz, version, data_version, default_block, default_biome, get_water);
|
|
519
|
+
}
|
|
520
|
+
else if (data_version >= 1466) {
|
|
521
|
+
return _decode_java_chunk<1466>(game_version, raw_chunk, *region, cx, cz, version, data_version, default_block, default_biome, get_water);
|
|
522
|
+
}
|
|
523
|
+
else if (data_version >= 1444) {
|
|
524
|
+
return _decode_java_chunk<1444>(game_version, raw_chunk, *region, cx, cz, version, data_version, default_block, default_biome, get_water);
|
|
525
|
+
}
|
|
526
|
+
else if (data_version >= 0) {
|
|
527
|
+
return _decode_java_chunk<0>(game_version, raw_chunk, *region, cx, cz, version, data_version, default_block, default_biome, get_water);
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
return _decode_java_chunk<-1>(game_version, raw_chunk, *region, cx, cz, version, data_version, default_block, default_biome, get_water);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <memory>
|
|
3
|
+
#include <map>
|
|
4
|
+
#include <cstdint>
|
|
5
|
+
|
|
6
|
+
#include <pybind11/pybind11.h>
|
|
7
|
+
|
|
8
|
+
#include <amulet_nbt/tag/named_tag.hpp>
|
|
9
|
+
|
|
10
|
+
#include <amulet/chunk.hpp>
|
|
11
|
+
#include <amulet/level/java/java_chunk.hpp>
|
|
12
|
+
|
|
13
|
+
namespace py = pybind11;
|
|
14
|
+
|
|
15
|
+
namespace Amulet {
|
|
16
|
+
std::shared_ptr<Amulet::JavaChunk> decode_java_chunk(
|
|
17
|
+
py::object raw_level,
|
|
18
|
+
py::object dimension,
|
|
19
|
+
std::map<std::string, AmuletNBT::NamedTag>& raw_chunk,
|
|
20
|
+
std::int64_t cx,
|
|
21
|
+
std::int64_t cz
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#include <memory>
|
|
2
|
+
#include <map>
|
|
3
|
+
#include <cstdint>
|
|
4
|
+
#include <stdexcept>
|
|
5
|
+
|
|
6
|
+
#include <pybind11/pybind11.h>
|
|
7
|
+
|
|
8
|
+
#include <amulet_nbt/tag/named_tag.hpp>
|
|
9
|
+
|
|
10
|
+
#include <amulet/chunk.hpp>
|
|
11
|
+
#include <amulet/level/java/java_chunk.hpp>
|
|
12
|
+
|
|
13
|
+
namespace py = pybind11;
|
|
14
|
+
|
|
15
|
+
namespace Amulet {
|
|
16
|
+
std::map<std::string, AmuletNBT::NamedTag> encode_java_chunk(
|
|
17
|
+
py::object raw_level,
|
|
18
|
+
py::object dimension,
|
|
19
|
+
std::shared_ptr<Amulet::JavaChunk> chunk,
|
|
20
|
+
std::int64_t cx,
|
|
21
|
+
std::int64_t cz
|
|
22
|
+
) {
|
|
23
|
+
throw std::runtime_error("");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <memory>
|
|
3
|
+
#include <map>
|
|
4
|
+
#include <cstdint>
|
|
5
|
+
|
|
6
|
+
#include <pybind11/pybind11.h>
|
|
7
|
+
|
|
8
|
+
#include <amulet_nbt/tag/named_tag.hpp>
|
|
9
|
+
|
|
10
|
+
#include <amulet/chunk.hpp>
|
|
11
|
+
#include <amulet/level/java/java_chunk.hpp>
|
|
12
|
+
|
|
13
|
+
namespace py = pybind11;
|
|
14
|
+
|
|
15
|
+
namespace Amulet {
|
|
16
|
+
std::map<std::string, AmuletNBT::NamedTag> encode_java_chunk(
|
|
17
|
+
py::object raw_level,
|
|
18
|
+
py::object dimension,
|
|
19
|
+
std::shared_ptr<Amulet::JavaChunk> chunk,
|
|
20
|
+
std::int64_t cx,
|
|
21
|
+
std::int64_t cz
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#include <cstdint>
|
|
2
|
+
#include <optional>
|
|
3
|
+
|
|
4
|
+
#include <amulet/io/binary_writer.hpp>
|
|
5
|
+
#include <amulet/io/binary_reader.hpp>
|
|
6
|
+
|
|
7
|
+
#include <amulet/level/java/chunk_components/data_version_component.hpp>
|
|
8
|
+
|
|
9
|
+
namespace Amulet {
|
|
10
|
+
const std::string DataVersionComponent::ComponentID = "Amulet::DataVersionComponent";
|
|
11
|
+
|
|
12
|
+
std::optional<std::string> DataVersionComponent::serialise() const {
|
|
13
|
+
if (_data_version) {
|
|
14
|
+
BinaryWriter writer;
|
|
15
|
+
writer.writeNumeric<std::int64_t>(_data_version.value());
|
|
16
|
+
return writer.getBuffer();
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
return std::nullopt;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
void DataVersionComponent::deserialise(std::optional<std::string> data) {
|
|
23
|
+
if (data) {
|
|
24
|
+
size_t position = 0;
|
|
25
|
+
BinaryReader reader(data.value(), position);
|
|
26
|
+
_data_version = reader.readNumeric<std::int64_t>();
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
_data_version = std::nullopt;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <optional>
|
|
4
|
+
#include <cstdint>
|
|
5
|
+
#include <string>
|
|
6
|
+
#include <stdexcept>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
namespace Amulet {
|
|
10
|
+
class DataVersionComponent {
|
|
11
|
+
private:
|
|
12
|
+
std::optional<std::int64_t> _data_version;
|
|
13
|
+
protected:
|
|
14
|
+
// Null constructor
|
|
15
|
+
DataVersionComponent() {};
|
|
16
|
+
// Default constructor
|
|
17
|
+
void init(std::int64_t data_version) { _data_version = data_version; }
|
|
18
|
+
// Serialise the component data
|
|
19
|
+
std::optional<std::string> serialise() const;
|
|
20
|
+
// Deserialise the component
|
|
21
|
+
void deserialise(std::optional<std::string>);
|
|
22
|
+
public:
|
|
23
|
+
static const std::string ComponentID;
|
|
24
|
+
std::int64_t get_data_version() {
|
|
25
|
+
if (_data_version) {
|
|
26
|
+
return *_data_version;
|
|
27
|
+
}
|
|
28
|
+
throw std::runtime_error("DataVersionComponent has not been loaded.");
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
}
|