summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--serialize/world-impl.hpp10
-rw-r--r--serialize/world-reader.cpp14
-rw-r--r--serialize/world-writer.cpp27
3 files changed, 38 insertions, 13 deletions
diff --git a/serialize/world-impl.hpp b/serialize/world-impl.hpp
index 252f361e..4cff8794 100644
--- a/serialize/world-impl.hpp
+++ b/serialize/world-impl.hpp
@@ -10,7 +10,7 @@ namespace floormat::Serialize {
namespace {
using tilemeta = std::uint8_t;
-using imgvar = decltype(tile_image::variant);
+using varid = decltype(tile_image::variant);
using atlasid = std::uint16_t;
using chunksiz = std::uint16_t;
using enum tile::pass_mode;
@@ -29,9 +29,11 @@ constexpr inline std::underlying_type_t<tile::pass_mode> pass_mask = pass_blocke
constexpr inline auto pass_bits = std::bit_width(pass_mask);
enum : tilemeta {
- meta_ground = 1 << (pass_bits + 0),
- meta_wall_n = 1 << (pass_bits + 1),
- meta_wall_w = 1 << (pass_bits + 2),
+ meta_ground = 1 << (pass_bits + 0),
+ meta_wall_n = 1 << (pass_bits + 1),
+ meta_wall_w = 1 << (pass_bits + 2),
+ meta_short_atlasid = 1 << (pass_bits + 3),
+ meta_short_variant = 1 << (pass_bits + 4),
};
} // namespace
diff --git a/serialize/world-reader.cpp b/serialize/world-reader.cpp
index b999b5d4..6172703b 100644
--- a/serialize/world-reader.cpp
+++ b/serialize/world-reader.cpp
@@ -65,19 +65,23 @@ void reader_state::read_chunks(reader_t& s)
for (std::size_t i = 0; i < TILE_COUNT; i++)
{
const tilemeta flags = s.read<tilemeta>();
+ tile& t = chunk[i];
+ using uchar = std::uint8_t;
const auto make_atlas = [&]() -> tile_image {
- auto atlas = lookup_atlas(s.read<atlasid>());
- auto id = s.read<imgvar>();
- fm_assert(id < atlas->num_tiles());
- return { atlas, id };
+ auto id = flags & meta_short_atlasid ? (atlasid)(s.read<uchar>()) : s.read<atlasid>();
+ auto v = flags & meta_short_variant ? (varid) (s.read<uchar>()) : s.read<varid>();
+ auto atlas = lookup_atlas(id);
+ fm_assert(v < atlas->num_tiles());
+ return { atlas, v };
};
- tile& t = chunk[i];
+
if (flags & meta_ground)
t.ground = make_atlas();
if (flags & meta_wall_n)
t.wall_north = make_atlas();
if (flags & meta_wall_w)
t.wall_west = make_atlas();
+
switch (auto x = flags & pass_mask)
{
case tile::pass_shoot_through:
diff --git a/serialize/world-writer.cpp b/serialize/world-writer.cpp
index 1739f899..8b33d35e 100644
--- a/serialize/world-writer.cpp
+++ b/serialize/world-writer.cpp
@@ -40,7 +40,7 @@ private:
std::unordered_map<const void*, interned_atlas> tile_images;
};
-constexpr auto tile_size = sizeof(tilemeta) + (sizeof(atlasid) + sizeof(imgvar))*3;
+constexpr auto tile_size = sizeof(tilemeta) + (sizeof(atlasid) + sizeof(varid)) * 3;
constexpr auto chunkbuf_size =
sizeof(chunk_magic) + sizeof(chunk_coords) + tile_size * TILE_COUNT;
@@ -100,6 +100,20 @@ void writer_state::serialize_chunk(const chunk& c, chunk_coords coord)
flags |= meta_wall_n * (img_n != null_atlas);
flags |= meta_wall_w * (img_w != null_atlas);
+ using uchar = std::uint8_t;
+
+ constexpr auto ashortp = [](atlasid id) {
+ return id == null_atlas || id == (uchar)id;
+ };
+ constexpr auto vshortp = [](const tile_image& img) {
+ return !img.atlas || img.variant == (uchar)img.variant;
+ };
+
+ if (flags != 0 && ashortp(img_g) && ashortp(img_n) && ashortp(img_w))
+ flags |= meta_short_atlasid;
+ if (flags != 0 && vshortp(x.ground) && vshortp(x.wall_north) && vshortp(x.wall_west))
+ flags |= meta_short_variant;
+
fm_debug_assert((x.passability & pass_mask) == x.passability);
flags |= x.passability;
@@ -115,12 +129,17 @@ void writer_state::serialize_chunk(const chunk& c, chunk_coords coord)
check_atlas(x.wall_west);
#endif
+ const auto write = [&](atlasid x, varid v) {
+ flags & meta_short_atlasid ? s << (uchar) x : s << x;
+ flags & meta_short_variant ? s << (uchar) v : s << v;
+ };
+
if (img_g != null_atlas)
- s << img_g << x.ground.variant;
+ write(img_g, x.ground.variant);
if (img_n != null_atlas)
- s << img_n << x.wall_north.variant;
+ write(img_n, x.wall_north.variant);
if (img_w != null_atlas)
- s << img_w << x.wall_west.variant;
+ write(img_w, x.wall_west.variant);
}
const auto nbytes = s.bytes_written();