Skip to content

Commit 3d4ebbe

Browse files
Implement serialisation formats (#412)
1 parent e066fff commit 3d4ebbe

File tree

9 files changed

+163
-20
lines changed

9 files changed

+163
-20
lines changed

src/amulet/core/biome/biome.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Biome Biome::deserialise(BinaryReader& reader)
3434
return { platform, version, namespace_, base_name };
3535
}
3636
default:
37-
throw std::invalid_argument("Unsupported version " + std::to_string(version_number));
37+
throw std::invalid_argument("Unsupported Biome version " + std::to_string(version_number));
3838
}
3939
}
4040

src/amulet/core/block/block.py.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,15 @@ void init_block(py::module m_parent)
291291
py::tuple(py::cast(self.get_blocks())));
292292
});
293293

294+
BlockStack.def(
295+
py::pickle(
296+
[](const Amulet::BlockStack& self) -> py::bytes {
297+
return py::bytes(Amulet::serialise(self));
298+
},
299+
[](py::bytes state) {
300+
return Amulet::deserialise<Amulet::BlockStack>(state.cast<std::string>());
301+
}));
302+
294303
pyext::collections::def_Sequence_getitem_slice(BlockStack);
295304
pyext::collections::def_Sequence_contains(BlockStack);
296305
pyext::collections::def_Sequence_iter<Amulet::Block>(BlockStack);

src/amulet/core/block_entity/block_entity.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,42 @@
1+
#include <amulet/nbt/nbt_encoding/binary.hpp>
2+
13
#include <amulet/core/dll.hpp>
24

35
#include "block_entity.hpp"
46

57
namespace Amulet {
68

7-
void BlockEntity::serialise(BinaryWriter&) const
9+
void BlockEntity::serialise(BinaryWriter& writer) const
810
{
9-
throw std::runtime_error("NotImplementedError");
11+
writer.write_numeric<std::uint8_t>(1);
12+
writer.write_size_and_bytes(get_platform());
13+
get_version().serialise(writer);
14+
writer.write_size_and_bytes(_namespace);
15+
writer.write_size_and_bytes(_base_name);
16+
Amulet::NBT::encode_nbt(writer, *_nbt);
1017
}
1118

12-
BlockEntity BlockEntity::deserialise(BinaryReader&)
19+
BlockEntity BlockEntity::deserialise(BinaryReader& reader)
1320
{
14-
throw std::runtime_error("NotImplementedError");
21+
auto version_number = reader.read_numeric<std::uint8_t>();
22+
switch (version_number) {
23+
case 1: {
24+
std::string platform { reader.read_size_and_bytes() };
25+
VersionNumber version = VersionNumber::deserialise(reader);
26+
std::string namespace_ { reader.read_size_and_bytes() };
27+
std::string base_name { reader.read_size_and_bytes() };
28+
auto named_tag = std::make_shared<Amulet::NBT::NamedTag>(Amulet::NBT::decode_nbt(reader));
29+
return BlockEntity {
30+
std::move(platform),
31+
std::move(version),
32+
std::move(namespace_),
33+
std::move(base_name),
34+
std::move(named_tag)
35+
};
36+
}
37+
default:
38+
throw std::invalid_argument("Unsupported BlockEntity version " + std::to_string(version_number));
39+
}
1540
}
1641

1742
bool BlockEntity::operator==(const BlockEntity& other) const

src/amulet/core/chunk/component/biome_3d_component.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,42 @@ namespace Amulet {
66

77
// Biome3DComponent
88

9+
void Biome3DComponentData::serialise(BinaryWriter& writer) const
10+
{
11+
writer.write_numeric<std::uint8_t>(1);
12+
_palette->serialise(writer);
13+
_sections->serialise(writer);
14+
}
15+
Biome3DComponentData Biome3DComponentData::deserialise(BinaryReader& reader)
16+
{
17+
auto version_number = reader.read_numeric<std::uint8_t>();
18+
switch (version_number) {
19+
case 1: {
20+
auto palette = std::make_shared<BiomePalette>(BiomePalette::deserialise(reader));
21+
auto sections = std::make_shared<SectionArrayMap>(SectionArrayMap::deserialise(reader));
22+
return Biome3DComponentData { std::move(palette), std::move(sections) };
23+
}
24+
default:
25+
throw std::invalid_argument("Unsupported Biome3DComponentData version " + std::to_string(version_number));
26+
}
27+
}
28+
929
std::optional<std::string> Biome3DComponent::serialise() const
1030
{
11-
throw std::runtime_error("NotImplementedError");
31+
if (_value) {
32+
return Amulet::serialise(**_value);
33+
} else {
34+
return std::nullopt;
35+
}
1236
}
1337
// Deserialise the component
14-
void Biome3DComponent::deserialise(std::optional<std::string>)
38+
void Biome3DComponent::deserialise(std::optional<std::string> data)
1539
{
16-
throw std::runtime_error("NotImplementedError");
40+
if (data) {
41+
_value = std::make_shared<Biome3DComponentData>(Amulet::deserialise<Biome3DComponentData>(*data));
42+
} else {
43+
_value = std::nullopt;
44+
}
1745
}
1846

1947
const std::string Biome3DComponent::ComponentID = "Amulet::Biome3DComponent";

src/amulet/core/chunk/component/biome_3d_component.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ class Biome3DComponentData {
5959
std::shared_ptr<BiomePalette> get_palette_ptr() { return _palette; }
6060
SectionArrayMap& get_sections() { return *_sections; }
6161
std::shared_ptr<SectionArrayMap> get_sections_ptr() { return _sections; }
62+
63+
AMULET_CORE_EXPORT void serialise(BinaryWriter&) const;
64+
AMULET_CORE_EXPORT static Biome3DComponentData deserialise(BinaryReader&);
6265
};
6366

6467
class Biome3DComponent {

src/amulet/core/chunk/component/block_entity_component.cpp

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,47 @@ namespace Amulet {
66

77
// BlockEntityComponentData
88

9-
void BlockEntityComponentData::serialise(BinaryWriter&) const
9+
void BlockEntityComponentData::serialise(BinaryWriter& writer) const
1010
{
11-
throw std::runtime_error("NotImplementedError");
11+
writer.write_numeric<std::uint8_t>(1);
12+
get_version_range().serialise(writer);
13+
writer.write_numeric<std::uint16_t>(get_x_size());
14+
writer.write_numeric<std::uint16_t>(get_z_size());
15+
16+
writer.write_numeric<std::uint64_t>(get_block_entities().size());
17+
for (const auto& [coord, block_entity] : get_block_entities()) {
18+
writer.write_numeric<std::uint16_t>(std::get<0>(coord));
19+
writer.write_numeric<std::int64_t>(std::get<1>(coord));
20+
writer.write_numeric<std::uint16_t>(std::get<2>(coord));
21+
block_entity->serialise(writer);
22+
}
1223
}
13-
BlockEntityComponentData BlockEntityComponentData::deserialise(BinaryReader&)
24+
BlockEntityComponentData BlockEntityComponentData::deserialise(BinaryReader& reader)
1425
{
15-
throw std::runtime_error("NotImplementedError");
26+
auto version_number = reader.read_numeric<std::uint8_t>();
27+
switch (version_number) {
28+
case 1: {
29+
auto version_range = VersionRange::deserialise(reader);
30+
auto x_size = reader.read_numeric<std::uint16_t>();
31+
auto z_size = reader.read_numeric<std::uint16_t>();
32+
BlockEntityComponentData block_entities {
33+
std::move(version_range),
34+
x_size,
35+
z_size
36+
};
37+
auto block_entity_count = reader.read_numeric<std::uint64_t>();
38+
for (std::uint16_t i = 0; i < block_entity_count; i++) {
39+
auto dx = reader.read_numeric<std::uint16_t>();
40+
auto y = reader.read_numeric<std::int64_t>();
41+
auto dz = reader.read_numeric<std::uint16_t>();
42+
auto block_entity = std::make_shared<BlockEntity>(BlockEntity::deserialise(reader));
43+
block_entities.set({ dx, y, dz }, std::move(block_entity));
44+
}
45+
return block_entities;
46+
}
47+
default:
48+
throw std::invalid_argument("Unsupported BlockEntityComponentData version " + std::to_string(version_number));
49+
}
1650
}
1751

1852
// BlockEntityComponent

src/amulet/core/chunk/component/section_array_map.py.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,5 +233,14 @@ py::module init_section_array_map(py::module m_parent)
233233
pyext::collections::def_MutableMapping_setdefault<std::int64_t, pyext::numpy::array_t<std::uint32_t>>(SectionArrayMap);
234234
pyext::collections::register_MutableMapping(SectionArrayMap);
235235

236+
SectionArrayMap.def(
237+
py::pickle(
238+
[](const Amulet::SectionArrayMap& self) -> py::bytes {
239+
return py::bytes(Amulet::serialise(self));
240+
},
241+
[](py::bytes state) {
242+
return Amulet::deserialise<Amulet::SectionArrayMap>(state.cast<std::string>());
243+
}));
244+
236245
return m;
237246
}

src/amulet/core/entity/entity.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,52 @@
1+
#include <amulet/nbt/nbt_encoding/binary.hpp>
2+
13
#include <amulet/core/dll.hpp>
24
#include <amulet/core/version/version.hpp>
35

46
#include "entity.hpp"
57

68
namespace Amulet {
79

8-
void Entity::serialise(BinaryWriter&) const
10+
void Entity::serialise(BinaryWriter& writer) const
911
{
10-
throw std::runtime_error("NotImplementedError");
12+
writer.write_numeric<std::uint8_t>(1);
13+
writer.write_size_and_bytes(get_platform());
14+
get_version().serialise(writer);
15+
writer.write_size_and_bytes(_namespace);
16+
writer.write_size_and_bytes(_base_name);
17+
writer.write_numeric<double>(_x);
18+
writer.write_numeric<double>(_y);
19+
writer.write_numeric<double>(_z);
20+
Amulet::NBT::encode_nbt(writer, *_nbt);
1121
}
12-
Entity Entity::deserialise(BinaryReader&)
22+
23+
Entity Entity::deserialise(BinaryReader& reader)
1324
{
14-
throw std::runtime_error("NotImplementedError");
25+
auto version_number = reader.read_numeric<std::uint8_t>();
26+
switch (version_number) {
27+
case 1: {
28+
std::string platform { reader.read_size_and_bytes() };
29+
VersionNumber version = VersionNumber::deserialise(reader);
30+
std::string namespace_ { reader.read_size_and_bytes() };
31+
std::string base_name { reader.read_size_and_bytes() };
32+
double x = reader.read_numeric<double>();
33+
double y = reader.read_numeric<double>();
34+
double z = reader.read_numeric<double>();
35+
auto named_tag = std::make_shared<Amulet::NBT::NamedTag>(Amulet::NBT::decode_nbt(reader));
36+
return Entity {
37+
std::move(platform),
38+
std::move(version),
39+
std::move(namespace_),
40+
std::move(base_name),
41+
x,
42+
y,
43+
z,
44+
std::move(named_tag)
45+
};
46+
}
47+
default:
48+
throw std::invalid_argument("Unsupported BlockEntity version " + std::to_string(version_number));
49+
}
1550
}
1651

1752
bool Entity::operator==(const Entity& other) const

src/amulet/core/version/version.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ VersionNumber VersionNumber::deserialise(BinaryReader& reader)
3131
return vec;
3232
}
3333
default:
34-
throw std::invalid_argument("Unsupported version " + std::to_string(version_number));
34+
throw std::invalid_argument("Unsupported VersionNumber version " + std::to_string(version_number));
3535
}
3636
}
3737

@@ -89,7 +89,7 @@ PlatformVersionContainer PlatformVersionContainer::deserialise(BinaryReader& rea
8989
return { platform, version };
9090
}
9191
default:
92-
throw std::invalid_argument("Unsupported version " + std::to_string(version_number));
92+
throw std::invalid_argument("Unsupported PlatformVersionContainer version " + std::to_string(version_number));
9393
}
9494
}
9595

@@ -112,7 +112,7 @@ VersionRange VersionRange::deserialise(BinaryReader& reader)
112112
return { platform, min_version, max_version };
113113
}
114114
default:
115-
throw std::invalid_argument("Unsupported version " + std::to_string(version_number));
115+
throw std::invalid_argument("Unsupported VersionRange version " + std::to_string(version_number));
116116
}
117117
}
118118

@@ -140,7 +140,7 @@ VersionRangeContainer VersionRangeContainer::deserialise(BinaryReader& reader)
140140
return VersionRange::deserialise(reader);
141141
}
142142
default:
143-
throw std::invalid_argument("Unsupported version " + std::to_string(version_number));
143+
throw std::invalid_argument("Unsupported VersionRangeContainer version " + std::to_string(version_number));
144144
}
145145
}
146146

0 commit comments

Comments
 (0)