Skip to content

Commit 2321b35

Browse files
Fix replay response recording for retry handling (#3116)
* add yrp format 2.5 & rollback replay when MSG_RETRY * simplify * remove yrp 2.5 * fix to #3116 (#3124) * format * implement same logic on SingleMode --------- Co-authored-by: Mercury233 <me@mercury233.me>
1 parent c896c5e commit 2321b35

8 files changed

Lines changed: 50 additions & 7 deletions

File tree

gframe/replay.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,31 @@ void Replay::WriteData(const void* data, size_t length, bool flush) {
4747
void Replay::WriteInt32(int32_t data, bool flush) {
4848
Write<int32_t>(data, flush);
4949
}
50+
size_t Replay::WriteResponse(const void* data, size_t length) {
51+
if(!is_recording || !data)
52+
return 0;
53+
const size_t response_length = std::min<size_t>(length, UINT8_MAX);
54+
if(!response_length)
55+
return 0;
56+
const size_t total_length = sizeof(uint8_t) + response_length;
57+
if(total_length > MAX_REPLAY_SIZE - replay_size)
58+
return 0;
59+
Write<uint8_t>(static_cast<uint8_t>(response_length), false);
60+
WriteData(data, response_length);
61+
return total_length;
62+
}
63+
bool Replay::RemoveData(size_t length) {
64+
if(!is_recording)
65+
return false;
66+
if(length > replay_size)
67+
return false;
68+
replay_size -= length;
69+
if(fp) {
70+
std::fflush(fp);
71+
std::fseek(fp, -static_cast<long>(length), SEEK_CUR);
72+
}
73+
return true;
74+
}
5075
void Replay::Flush() {
5176
if(!is_recording)
5277
return;
@@ -189,7 +214,7 @@ bool Replay::RenameReplay(const wchar_t* oldname, const wchar_t* newname) {
189214
return FileSystem::Rename(old_path, new_path);
190215
}
191216
bool Replay::ReadNextResponse(unsigned char resp[]) {
192-
unsigned char len{};
217+
uint8_t len{};
193218
if (!ReadData(&len, sizeof len))
194219
return false;
195220
if (!ReadData(resp, len))

gframe/replay.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ class Replay {
6363
WriteData(&data, sizeof(T), flush);
6464
}
6565
void WriteInt32(int32_t data, bool flush = true);
66+
size_t WriteResponse(const void* data, size_t length);
67+
bool RemoveData(size_t length);
6668
void Flush();
6769
void EndRecord();
6870
bool SaveReplay(const wchar_t* base_name);

gframe/single_duel.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,10 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
581581
unsigned char engType = BufferIO::Read<uint8_t>(pbuf);
582582
switch (engType) {
583583
case MSG_RETRY: {
584+
if(last_replay_response_size) {
585+
last_replay.RemoveData(last_replay_response_size);
586+
last_replay_response_size = 0;
587+
}
584588
WaitforResponse(last_response);
585589
NetServer::SendBufferToPlayer(players[last_response], STOC_GAME_MSG, offset, pbuf - offset);
586590
return 1;
@@ -1416,8 +1420,7 @@ void SingleDuel::GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int
14161420
if (len > UINT8_MAX)
14171421
len = UINT8_MAX;
14181422
std::memcpy(resb, pdata, len);
1419-
last_replay.Write<uint8_t>(len);
1420-
last_replay.WriteData(resb, len);
1423+
last_replay_response_size = last_replay.WriteResponse(resb, len);
14211424
set_responseb(pduel, resb);
14221425
players[dp->type]->state = 0xff;
14231426
if(host_info.time_limit) {
@@ -1427,6 +1430,7 @@ void SingleDuel::GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int
14271430
time_elapsed = 0;
14281431
}
14291432
Process();
1433+
last_replay_response_size = 0;
14301434
}
14311435
void SingleDuel::EndDuel() {
14321436
if(!pduel)

gframe/single_duel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class SingleDuel: public DuelMode {
5555
unsigned char last_response{ 0 };
5656
std::set<DuelPlayer*> observers;
5757
Replay last_replay;
58+
size_t last_replay_response_size{ 0 };
5859
bool match_mode{ false };
5960
int match_kill{ 0 };
6061
unsigned char duel_count{ 0 };

gframe/single_mode.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ intptr_t SingleMode::pduel = 0;
1111
bool SingleMode::is_closing = false;
1212
bool SingleMode::is_continuing = false;
1313
Replay SingleMode::last_replay;
14+
size_t SingleMode::last_replay_response_size = 0;
1415

1516
bool SingleMode::StartPlay() {
1617
std::thread(SinglePlayThread).detach();
@@ -25,8 +26,7 @@ void SingleMode::StopPlay(bool is_exiting) {
2526
void SingleMode::SetResponse(unsigned char* resp, unsigned int len) {
2627
if(!pduel)
2728
return;
28-
last_replay.Write<uint8_t>(len);
29-
last_replay.WriteData(resp, len);
29+
last_replay_response_size = last_replay.WriteResponse(resp, len);
3030
set_responseb(pduel, resp);
3131
}
3232
int SingleMode::SinglePlayThread() {
@@ -112,6 +112,7 @@ int SingleMode::SinglePlayThread() {
112112
if (len > 0)
113113
is_continuing = SinglePlayAnalyze(engineBuffer.data(), len);
114114
last_replay.BeginRecord();
115+
last_replay_response_size = 0;
115116
last_replay.WriteHeader(rh);
116117
uint16_t host_name[20]{};
117118
BufferIO::CopyCharArray(mainGame->dInfo.hostname, host_name);
@@ -191,6 +192,10 @@ bool SingleMode::SinglePlayAnalyze(unsigned char* msg, unsigned int len) {
191192
mainGame->dInfo.curMsg = BufferIO::Read<uint8_t>(pbuf);
192193
switch (mainGame->dInfo.curMsg) {
193194
case MSG_RETRY: {
195+
if(last_replay_response_size) {
196+
last_replay.RemoveData(last_replay_response_size);
197+
last_replay_response_size = 0;
198+
}
194199
if(!DuelClient::ClientAnalyze(offset, pbuf - offset)) {
195200
mainGame->singleSignal.Reset();
196201
mainGame->singleSignal.Wait();

gframe/single_mode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class SingleMode {
3434

3535
protected:
3636
static Replay last_replay;
37+
static size_t last_replay_response_size;
3738
};
3839

3940
}

gframe/tag_duel.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,10 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
545545
unsigned char engType = BufferIO::Read<uint8_t>(pbuf);
546546
switch (engType) {
547547
case MSG_RETRY: {
548+
if(last_replay_response_size) {
549+
last_replay.RemoveData(last_replay_response_size);
550+
last_replay_response_size = 0;
551+
}
548552
WaitforResponse(last_response);
549553
NetServer::SendBufferToPlayer(cur_player[last_response], STOC_GAME_MSG, offset, pbuf - offset);
550554
return 1;
@@ -1522,8 +1526,7 @@ void TagDuel::GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len
15221526
if (len > UINT8_MAX)
15231527
len = UINT8_MAX;
15241528
std::memcpy(resb, pdata, len);
1525-
last_replay.Write<uint8_t>(len);
1526-
last_replay.WriteData(resb, len);
1529+
last_replay_response_size = last_replay.WriteResponse(resb, len);
15271530
set_responseb(pduel, resb);
15281531
players[dp->type]->state = 0xff;
15291532
if(host_info.time_limit) {
@@ -1534,6 +1537,7 @@ void TagDuel::GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len
15341537
time_elapsed = 0;
15351538
}
15361539
Process();
1540+
last_replay_response_size = 0;
15371541
}
15381542
void TagDuel::EndDuel() {
15391543
if(!pduel)

gframe/tag_duel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class TagDuel: public DuelMode {
5757
unsigned char hand_result[2];
5858
unsigned char last_response;
5959
Replay last_replay;
60+
size_t last_replay_response_size{ 0 };
6061
unsigned char turn_count;
6162
short time_limit[2];
6263
short time_elapsed;

0 commit comments

Comments
 (0)