33#include " utils.hpp"
44
55void Replay::remove_actions_after (float x) {
6- auto check = [&](const Action& action) -> bool {
6+ const auto check = [&](const Action& action) -> bool {
77 return action.x >= x;
88 };
99 actions.erase (std::remove_if (actions.begin (), actions.end (), check), actions.end ());
1010}
1111
12+ void Replay::remove_actions_after (unsigned frame) {
13+ const auto check = [&](const Action& action) -> bool {
14+ return action.frame >= frame;
15+ };
16+ actions.erase (std::remove_if (actions.begin (), actions.end (), check), actions.end ());
17+ }
18+
1219// these two functions are so stupid
1320// why cant c++ do it for me :(
1421
@@ -24,17 +31,33 @@ inline T bin_read(std::ifstream& stream) {
2431 return value;
2532}
2633
27- constexpr uint8_t format_ver = 1 ;
28- constexpr const char format_magic[5 ] = " RPLY" ;
34+ /*
35+ * Format changelog
36+ *
37+ * - version 1
38+ * header | action[]
39+ * header: "RPLY" | version as u8 | fps as f32
40+ * action: x as f32 | state as u8
41+ *
42+ * - version 2
43+ * add `type as u8` between version and fps
44+ * change action x to be either float or an unsigned int
45+ */
46+
47+ constexpr uint8_t format_ver = 2 ;
48+ constexpr const char format_magic[4 ] = {' R' , ' P' , ' L' , ' Y' };
2949
3050void Replay::save (const std::string& path) {
3151 std::ofstream file;
3252 file.open (path, std::ios::binary | std::ios::out);
33- file << format_magic << format_ver;
53+ file << format_magic << format_ver << type ;
3454 bin_write (file, fps);
3555 for (const auto & action : actions) {
3656 uint8_t state = action.hold | action.player2 << 1 ;
37- bin_write (file, action.x );
57+ if (type == ReplayType::XPOS)
58+ bin_write (file, action.x );
59+ else if (type == ReplayType::FRAME)
60+ bin_write (file, action.frame );
3861 file << state;
3962 }
4063 file.close ();
@@ -53,19 +76,25 @@ Replay Replay::load(const std::string& path) {
5376 file.read (magic, 4 );
5477 if (memcmp (magic, format_magic, 4 ) == 0 ) {
5578 auto ver = bin_read<uint8_t >(file);
56- if (ver == 1 ) {
79+ if (ver == 1 || ver == 2 ) {
80+ if (ver == 2 ) replay.type = ReplayType (bin_read<uint8_t >(file));
5781 replay.fps = bin_read<float >(file);
5882 size_t left = file_size - static_cast <size_t >(file.tellg ());
83+ float x;
84+ unsigned frame;
5985 for (size_t _ = 0 ; _ < left / 5 ; ++_) {
60- float x = bin_read<float >(file);
86+ if (replay.type == ReplayType::XPOS)
87+ x = bin_read<float >(file);
88+ else if (replay.type == ReplayType::FRAME)
89+ frame = bin_read<unsigned >(file);
6190 auto state = bin_read<uint8_t >(file);
6291 bool hold = state & 1 ;
6392 bool player2 = state & 2 ;
64- replay.add_action ({ x , hold, player2 });
93+ replay.add_action ({ replay. type == ReplayType::XPOS ? x : frame , hold, player2 });
6594 }
6695 }
6796 } else {
68- replay.fps = *reinterpret_cast <float *>(&magic);
97+ replay.fps = *cast <float *>(&magic);
6998 size_t left = file_size - static_cast <size_t >(file.tellg ());
7099 for (size_t _ = 0 ; _ < left / 6 ; ++_) {
71100 float x = bin_read<float >(file);
0 commit comments