Commit 3516ba98 authored by edo9300's avatar edo9300

Merge remote-tracking branch 'refs/remotes/origin/new-replay-system'

parents 80ffa24b 38ff205e
...@@ -53,6 +53,7 @@ ClientCard::ClientCard() { ...@@ -53,6 +53,7 @@ ClientCard::ClientCard() {
void ClientCard::SetCode(int code) { void ClientCard::SetCode(int code) {
if((location == LOCATION_HAND) && (this->code != (unsigned int)code)) { if((location == LOCATION_HAND) && (this->code != (unsigned int)code)) {
this->code = code; this->code = code;
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping)
mainGame->dField.MoveCard(this, 5); mainGame->dField.MoveCard(this, 5);
} else } else
this->code = code; this->code = code;
...@@ -66,6 +67,7 @@ void ClientCard::UpdateInfo(char* buf) { ...@@ -66,6 +67,7 @@ void ClientCard::UpdateInfo(char* buf) {
pdata = BufferIO::ReadInt32(buf); pdata = BufferIO::ReadInt32(buf);
if((location == LOCATION_HAND) && ((unsigned int)pdata != code)) { if((location == LOCATION_HAND) && ((unsigned int)pdata != code)) {
code = pdata; code = pdata;
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping)
mainGame->dField.MoveCard(this, 5); mainGame->dField.MoveCard(this, 5);
} else } else
code = pdata; code = pdata;
......
...@@ -26,6 +26,10 @@ u64 DuelClient::select_hint = 0; ...@@ -26,6 +26,10 @@ u64 DuelClient::select_hint = 0;
wchar_t DuelClient::event_string[256]; wchar_t DuelClient::event_string[256];
mtrandom DuelClient::rnd; mtrandom DuelClient::rnd;
std::vector<ReplayPacket> DuelClient::replay_stream;
Replay DuelClient::last_replay;
bool DuelClient::old_replay = true;
bool DuelClient::is_refreshing = false; bool DuelClient::is_refreshing = false;
int DuelClient::match_kill = 0; int DuelClient::match_kill = 0;
std::vector<HostPacket> DuelClient::hosts; std::vector<HostPacket> DuelClient::hosts;
...@@ -693,43 +697,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -693,43 +697,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->btnSideReload->setVisible(false); mainGame->btnSideReload->setVisible(false);
mainGame->wChat->setVisible(true); mainGame->wChat->setVisible(true);
mainGame->device->setEventReceiver(&mainGame->dField); mainGame->device->setEventReceiver(&mainGame->dField);
// reset master rule 4 phase button position mainGame->SetPhaseButtons();
mainGame->wPhase->setRelativePosition(mainGame->Resize(480, 310, 855, 330));
if(mainGame->dInfo.extraval & 0x1) {
if(mainGame->dInfo.duel_field >= 4) {
mainGame->wPhase->setRelativePosition(mainGame->Resize(480, 290, 855, 350));
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnDP->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnSP->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnM1->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnBP->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnM2->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnEP->setRelativePosition(mainGame->Resize(310, 0, 360, 20));
} else {
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnDP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnSP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(130, 0, 180, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(195, 0, 245, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
mainGame->btnEP->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
}
} else {
mainGame->btnDP->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
if(mainGame->dInfo.duel_field >= 4) {
mainGame->btnSP->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
} else {
mainGame->btnSP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(130, 0, 180, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(195, 0, 245, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
}
mainGame->btnEP->setRelativePosition(mainGame->Resize(320, 0, 370, 20));
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
}
if(!mainGame->dInfo.isTag) { if(!mainGame->dInfo.isTag) {
if(selftype > 1) { if(selftype > 1) {
mainGame->dInfo.player_type = 7; mainGame->dInfo.player_type = 7;
...@@ -767,6 +735,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -767,6 +735,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
} }
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
match_kill = 0; match_kill = 0;
replay_stream.clear();
old_replay = true;
break; break;
} }
case STOC_DUEL_END: { case STOC_DUEL_END: {
...@@ -803,6 +773,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -803,6 +773,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
break; break;
} }
case STOC_REPLAY: { case STOC_REPLAY: {
if (!old_replay) break;
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
mainGame->wPhase->setVisible(false); mainGame->wPhase->setVisible(false);
if(mainGame->dInfo.player_type < 7) if(mainGame->dInfo.player_type < 7)
...@@ -823,16 +794,28 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -823,16 +794,28 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
mainGame->replaySignal.Reset(); mainGame->replaySignal.Reset();
mainGame->replaySignal.Wait(); mainGame->replaySignal.Wait();
if(mainGame->actionParam || !is_host) { if(mainGame->saveReplay || !is_host) {
char* prep = pdata; char* prep = pdata;
Replay new_replay; ReplayHeader pheader;
memcpy(&new_replay.pheader, prep, sizeof(ReplayHeader)); memcpy(&pheader, prep, sizeof(ReplayHeader));
prep += sizeof(ReplayHeader); replay_stream.push_back(ReplayPacket(OLD_REPLAY_MODE, prep, len - 1));
memcpy(new_replay.comp_data, prep, len - sizeof(ReplayHeader) - 1); if(mainGame->saveReplay) {
new_replay.comp_size = len - sizeof(ReplayHeader) - 1; last_replay.BeginRecord(false);
if(mainGame->actionParam) last_replay.WriteHeader(pheader);
new_replay.SaveReplay(mainGame->ebRSName->getText()); last_replay.pheader.id = 0x58707279;
else new_replay.SaveReplay(L"_LastReplay"); last_replay.WriteData(mainGame->dInfo.hostname, 40, false);
last_replay.WriteData(mainGame->dInfo.clientname, 40, false);
if (last_replay.pheader.flag & REPLAY_TAG) {
last_replay.WriteData(mainGame->dInfo.hostname_tag, 40, false);
last_replay.WriteData(mainGame->dInfo.clientname_tag, 40, false);
}
last_replay.WriteInt32(mainGame->dInfo.duel_field | mainGame->dInfo.extraval >> 8);
last_replay.WriteStream(replay_stream);
last_replay.EndRecord();
}
if (mainGame->saveReplay)
last_replay.SaveReplay(mainGame->ebRSName->getText());
else last_replay.SaveReplay(L"_LastReplay");
} }
break; break;
} }
...@@ -975,12 +958,56 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -975,12 +958,56 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
break; break;
} }
case STOC_NEW_REPLAY: {
old_replay = false;
mainGame->gMutex.Lock();
mainGame->wPhase->setVisible(false);
if(mainGame->dInfo.player_type < 7)
mainGame->btnLeaveGame->setVisible(false);
mainGame->btnChainIgnore->setVisible(false);
mainGame->btnChainAlways->setVisible(false);
mainGame->btnChainWhenAvail->setVisible(false);
mainGame->btnCancelOrFinish->setVisible(false);
time_t nowtime = time(NULL);
struct tm *localedtime = localtime(&nowtime);
char timebuf[40];
strftime(timebuf, 40, "%Y-%m-%d %H-%M-%S", localedtime);
size_t size = strlen(timebuf) + 1;
wchar_t timetext[80];
mbstowcs(timetext, timebuf, size);
mainGame->ebRSName->setText(timetext);
mainGame->PopupElement(mainGame->wReplaySave);
mainGame->gMutex.Unlock();
mainGame->replaySignal.Reset();
mainGame->replaySignal.Wait();
if(mainGame->saveReplay || !is_host) {
char* prep = pdata;
Replay new_replay;
memcpy(&new_replay.pheader, prep, sizeof(ReplayHeader));
prep += sizeof(ReplayHeader);
memcpy(new_replay.comp_data, prep, len - sizeof(ReplayHeader) - 1);
new_replay.comp_size = len - sizeof(ReplayHeader) - 1;
if(mainGame->saveReplay)
new_replay.SaveReplay(mainGame->ebRSName->getText());
else new_replay.SaveReplay(L"_LastReplay");
}
break;
}
} }
} }
int DuelClient::ClientAnalyze(char * msg, unsigned int len) { int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
char* pbuf = msg; char* pbuf = msg;
wchar_t textBuffer[256]; wchar_t textBuffer[256];
if(!mainGame->dInfo.isReplay || mainGame->dInfo.isOldReplay) {
mainGame->dInfo.curMsg = BufferIO::ReadUInt8(pbuf); mainGame->dInfo.curMsg = BufferIO::ReadUInt8(pbuf);
if(mainGame->dInfo.curMsg != MSG_WAITING) {
ReplayPacket p;
p.message = mainGame->dInfo.curMsg;
p.length = len - 1;
memcpy(p.data, pbuf, p.length);
replay_stream.push_back(p);
}
}
mainGame->wCmdMenu->setVisible(false); mainGame->wCmdMenu->setVisible(false);
if(!mainGame->dInfo.isReplay && mainGame->dInfo.curMsg != MSG_WAITING && mainGame->dInfo.curMsg != MSG_CARD_SELECTED) { if(!mainGame->dInfo.isReplay && mainGame->dInfo.curMsg != MSG_WAITING && mainGame->dInfo.curMsg != MSG_CARD_SELECTED) {
mainGame->waitFrame = -1; mainGame->waitFrame = -1;
...@@ -1164,6 +1191,8 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -1164,6 +1191,8 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
return true; return true;
} }
case MSG_START: { case MSG_START: {
int playertype = BufferIO::ReadInt8(pbuf);
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) {
mainGame->showcardcode = 11; mainGame->showcardcode = 11;
mainGame->showcarddif = 30; mainGame->showcarddif = 30;
mainGame->showcardp = 0; mainGame->showcardp = 0;
...@@ -1171,8 +1200,8 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -1171,8 +1200,8 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
mainGame->WaitFrameSignal(40); mainGame->WaitFrameSignal(40);
mainGame->showcard = 0; mainGame->showcard = 0;
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
int playertype = BufferIO::ReadInt8(pbuf);
mainGame->dInfo.isFirst = (playertype & 0xf) ? false : true; mainGame->dInfo.isFirst = (playertype & 0xf) ? false : true;
}
if(playertype & 0xf0) if(playertype & 0xf0)
mainGame->dInfo.player_type = 7; mainGame->dInfo.player_type = 7;
if(mainGame->dInfo.isTag) { if(mainGame->dInfo.isTag) {
...@@ -1197,14 +1226,17 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -1197,14 +1226,17 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
mainGame->dField.Initial(mainGame->LocalPlayer(1), deckc, extrac); mainGame->dField.Initial(mainGame->LocalPlayer(1), deckc, extrac);
mainGame->dInfo.turn = 0; mainGame->dInfo.turn = 0;
mainGame->dInfo.is_shuffling = false; mainGame->dInfo.is_shuffling = false;
if (!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping)
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
return true; return true;
} }
case MSG_UPDATE_DATA: { case MSG_UPDATE_DATA: {
int player = mainGame->LocalPlayer(BufferIO::ReadInt8(pbuf)); int player = mainGame->LocalPlayer(BufferIO::ReadInt8(pbuf));
int location = BufferIO::ReadInt8(pbuf); int location = BufferIO::ReadInt8(pbuf);
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping)
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
mainGame->dField.UpdateFieldCard(player, location, pbuf); mainGame->dField.UpdateFieldCard(player, location, pbuf);
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping)
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
return true; return true;
} }
...@@ -1212,8 +1244,10 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -1212,8 +1244,10 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
int player = mainGame->LocalPlayer(BufferIO::ReadInt8(pbuf)); int player = mainGame->LocalPlayer(BufferIO::ReadInt8(pbuf));
int loc = BufferIO::ReadInt8(pbuf); int loc = BufferIO::ReadInt8(pbuf);
int seq = BufferIO::ReadInt8(pbuf); int seq = BufferIO::ReadInt8(pbuf);
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping)
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
mainGame->dField.UpdateCard(player, loc, seq, pbuf); mainGame->dField.UpdateCard(player, loc, seq, pbuf);
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping)
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
break; break;
} }
...@@ -3729,11 +3763,13 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -3729,11 +3763,13 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
break; break;
} }
case MSG_RELOAD_FIELD: { case MSG_RELOAD_FIELD: {
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping)
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
mainGame->dField.Clear(); mainGame->dField.Clear();
int field = BufferIO::ReadInt8(pbuf); int field = BufferIO::ReadInt8(pbuf);
mainGame->dInfo.duel_field = field & 0xf; mainGame->dInfo.duel_field = field & 0xf;
mainGame->dInfo.extraval = field >> 4; mainGame->dInfo.extraval = field >> 4;
mainGame->SetPhaseButtons();
int val = 0; int val = 0;
for(int i = 0; i < 2; ++i) { for(int i = 0; i < 2; ++i) {
int p = mainGame->LocalPlayer(i); int p = mainGame->LocalPlayer(i);
...@@ -3848,6 +3884,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -3848,6 +3884,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
myswprintf(event_string, dataManager.GetSysString(1609), dataManager.GetName(mainGame->dField.current_chain.code)); myswprintf(event_string, dataManager.GetSysString(1609), dataManager.GetName(mainGame->dField.current_chain.code));
mainGame->dField.last_chain = true; mainGame->dField.last_chain = true;
} }
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping)
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
break; break;
} }
...@@ -3914,10 +3951,11 @@ void DuelClient::SendResponse() { ...@@ -3914,10 +3951,11 @@ void DuelClient::SendResponse() {
break; break;
} }
} }
replay_stream.pop_back();
if(mainGame->dInfo.isSingleMode) { if(mainGame->dInfo.isSingleMode) {
SingleMode::SetResponse(response_buf, response_len); SingleMode::SetResponse(response_buf, response_len);
mainGame->singleSignal.Set(); mainGame->singleSignal.Set();
} else { } else if (!mainGame->dInfo.isReplay) {
mainGame->dInfo.time_player = 2; mainGame->dInfo.time_player = 2;
SendBufferToServer(CTOS_RESPONSE, response_buf, response_len); SendBufferToServer(CTOS_RESPONSE, response_buf, response_len);
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "data_manager.h" #include "data_manager.h"
#include "deck_manager.h" #include "deck_manager.h"
#include "../ocgcore/mtrandom.h" #include "../ocgcore/mtrandom.h"
#include "replay.h"
namespace ygo { namespace ygo {
...@@ -45,6 +46,9 @@ public: ...@@ -45,6 +46,9 @@ public:
static void ClientEvent(bufferevent *bev, short events, void *ctx); static void ClientEvent(bufferevent *bev, short events, void *ctx);
static int ClientThread(void* param); static int ClientThread(void* param);
static void HandleSTOCPacketLan(char* data, unsigned int len); static void HandleSTOCPacketLan(char* data, unsigned int len);
static std::vector<ReplayPacket> replay_stream;
static Replay last_replay;
static bool old_replay;
static int ClientAnalyze(char* msg, unsigned int len); static int ClientAnalyze(char* msg, unsigned int len);
static void SetResponseI(int respI); static void SetResponseI(int respI);
static void SetResponseB(void* respB, unsigned char len); static void SetResponseB(void* respB, unsigned char len);
......
...@@ -95,13 +95,13 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -95,13 +95,13 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
case BUTTON_REPLAY_SAVE: { case BUTTON_REPLAY_SAVE: {
if(mainGame->ebRSName->getText()[0] == 0) if(mainGame->ebRSName->getText()[0] == 0)
break; break;
mainGame->actionParam = 1; mainGame->saveReplay = 1;
mainGame->HideElement(mainGame->wReplaySave); mainGame->HideElement(mainGame->wReplaySave);
mainGame->replaySignal.Set(); mainGame->replaySignal.Set();
break; break;
} }
case BUTTON_REPLAY_CANCEL: { case BUTTON_REPLAY_CANCEL: {
mainGame->actionParam = 0; mainGame->saveReplay = 0;
mainGame->HideElement(mainGame->wReplaySave); mainGame->HideElement(mainGame->wReplaySave);
mainGame->replaySignal.Set(); mainGame->replaySignal.Set();
break; break;
......
...@@ -617,6 +617,7 @@ bool Game::Initialize() { ...@@ -617,6 +617,7 @@ bool Game::Initialize() {
btnReplayCancel = env->addButton(rect<s32>(460, 385, 570, 410), wReplay, BUTTON_CANCEL_REPLAY, dataManager.GetSysString(1347)); btnReplayCancel = env->addButton(rect<s32>(460, 385, 570, 410), wReplay, BUTTON_CANCEL_REPLAY, dataManager.GetSysString(1347));
env->addStaticText(dataManager.GetSysString(1349), rect<s32>(360, 30, 570, 50), false, true, wReplay); env->addStaticText(dataManager.GetSysString(1349), rect<s32>(360, 30, 570, 50), false, true, wReplay);
stReplayInfo = env->addStaticText(L"", rect<s32>(360, 60, 570, 350), false, true, wReplay); stReplayInfo = env->addStaticText(L"", rect<s32>(360, 60, 570, 350), false, true, wReplay);
chkYrp = env->addCheckBox(false, recti(360, 250, 560, 270), wReplay, -1, dataManager.GetSysString(1999));
env->addStaticText(dataManager.GetSysString(1353), rect<s32>(360, 275, 570, 295), false, true, wReplay); env->addStaticText(dataManager.GetSysString(1353), rect<s32>(360, 275, 570, 295), false, true, wReplay);
ebRepStartTurn = env->addEditBox(L"", rect<s32>(360, 300, 460, 320), true, wReplay, -1); ebRepStartTurn = env->addEditBox(L"", rect<s32>(360, 300, 460, 320), true, wReplay, -1);
ebRepStartTurn->setTextAlignment(irr::gui::EGUIA_CENTER, irr::gui::EGUIA_CENTER); ebRepStartTurn->setTextAlignment(irr::gui::EGUIA_CENTER, irr::gui::EGUIA_CENTER);
...@@ -1228,7 +1229,7 @@ bool Game::PlayChant(unsigned int code) { ...@@ -1228,7 +1229,7 @@ bool Game::PlayChant(unsigned int code) {
return false; return false;
} }
void Game::PlaySoundEffect(char* sound) { void Game::PlaySoundEffect(char* sound) {
if(chkEnableSound->isChecked()) { if(chkEnableSound->isChecked() && (!dInfo.isReplay || !dInfo.isReplaySkiping)) {
engineSound->play2D(sound); engineSound->play2D(sound);
engineSound->setSoundVolume(gameConf.volume); engineSound->setSoundVolume(gameConf.volume);
} }
...@@ -1563,8 +1564,46 @@ int Game::GetMasterRule(uint32 param, uint32 forbiddentypes, int* truerule) { ...@@ -1563,8 +1564,46 @@ int Game::GetMasterRule(uint32 param, uint32 forbiddentypes, int* truerule) {
} }
} }
} }
void Game::OnResize() void Game::SetPhaseButtons() {
{ // reset master rule 4 phase button position
wPhase->setRelativePosition(Resize(480, 310, 855, 330));
if (dInfo.extraval & 0x1) {
if (dInfo.duel_field >= 4) {
wPhase->setRelativePosition(Resize(480, 290, 855, 350));
btnShuffle->setRelativePosition(Resize(0, 40, 50, 60));
btnDP->setRelativePosition(Resize(0, 40, 50, 60));
btnSP->setRelativePosition(Resize(0, 40, 50, 60));
btnM1->setRelativePosition(Resize(160, 20, 210, 40));
btnBP->setRelativePosition(Resize(160, 20, 210, 40));
btnM2->setRelativePosition(Resize(160, 20, 210, 40));
btnEP->setRelativePosition(Resize(310, 0, 360, 20));
} else {
btnShuffle->setRelativePosition(Resize(65, 0, 115, 20));
btnDP->setRelativePosition(Resize(65, 0, 115, 20));
btnSP->setRelativePosition(Resize(65, 0, 115, 20));
btnM1->setRelativePosition(Resize(130, 0, 180, 20));
btnBP->setRelativePosition(Resize(195, 0, 245, 20));
btnM2->setRelativePosition(Resize(260, 0, 310, 20));
btnEP->setRelativePosition(Resize(260, 0, 310, 20));
}
} else {
btnDP->setRelativePosition(Resize(0, 0, 50, 20));
if (dInfo.duel_field >= 4) {
btnSP->setRelativePosition(Resize(0, 0, 50, 20));
btnM1->setRelativePosition(Resize(160, 0, 210, 20));
btnBP->setRelativePosition(Resize(160, 0, 210, 20));
btnM2->setRelativePosition(Resize(160, 0, 210, 20));
} else {
btnSP->setRelativePosition(Resize(65, 0, 115, 20));
btnM1->setRelativePosition(Resize(130, 0, 180, 20));
btnBP->setRelativePosition(Resize(195, 0, 245, 20));
btnM2->setRelativePosition(Resize(260, 0, 310, 20));
}
btnEP->setRelativePosition(Resize(320, 0, 370, 20));
btnShuffle->setRelativePosition(Resize(0, 0, 50, 20));
}
}
void Game::OnResize() {
wMainMenu->setRelativePosition(ResizeWin(370, 200, 650, 415)); wMainMenu->setRelativePosition(ResizeWin(370, 200, 650, 415));
wDeckEdit->setRelativePosition(Resize(309, 8, 605, 130)); wDeckEdit->setRelativePosition(Resize(309, 8, 605, 130));
cbDBLFList->setRelativePosition(Resize(80, 5, 220, 30)); cbDBLFList->setRelativePosition(Resize(80, 5, 220, 30));
...@@ -1662,42 +1701,7 @@ void Game::OnResize() ...@@ -1662,42 +1701,7 @@ void Game::OnResize()
btnReplaySwap->setRelativePosition(Resize(5, 30, 85, 50)); btnReplaySwap->setRelativePosition(Resize(5, 30, 85, 50));
btnReplayExit->setRelativePosition(Resize(5, 105, 85, 125)); btnReplayExit->setRelativePosition(Resize(5, 105, 85, 125));
wPhase->setRelativePosition(Resize(480, 310, 855, 330)); SetPhaseButtons();
if(dInfo.extraval & 0x1) {
if(dInfo.duel_field >= 4) {
wPhase->setRelativePosition(Resize(480, 290, 855, 350));
btnShuffle->setRelativePosition(Resize(0, 40, 50, 60));
btnDP->setRelativePosition(Resize(0, 40, 50, 60));
btnSP->setRelativePosition(Resize(0, 40, 50, 60));
btnM1->setRelativePosition(Resize(160, 20, 210, 40));
btnBP->setRelativePosition(Resize(160, 20, 210, 40));
btnM2->setRelativePosition(Resize(160, 20, 210, 40));
btnEP->setRelativePosition(Resize(310, 0, 360, 20));
} else {
btnShuffle->setRelativePosition(Resize(65, 0, 115, 20));
btnDP->setRelativePosition(Resize(65, 0, 115, 20));
btnSP->setRelativePosition(Resize(65, 0, 115, 20));
btnM1->setRelativePosition(Resize(130, 0, 180, 20));
btnBP->setRelativePosition(Resize(195, 0, 245, 20));
btnM2->setRelativePosition(Resize(260, 0, 310, 20));
btnEP->setRelativePosition(Resize(260, 0, 310, 20));
}
} else {
btnDP->setRelativePosition(Resize(0, 0, 50, 20));
if(dInfo.duel_field >= 4) {
btnSP->setRelativePosition(Resize(0, 0, 50, 20));
btnM1->setRelativePosition(Resize(160, 0, 210, 20));
btnBP->setRelativePosition(Resize(160, 0, 210, 20));
btnM2->setRelativePosition(Resize(160, 0, 210, 20));
} else {
btnSP->setRelativePosition(Resize(65, 0, 115, 20));
btnM1->setRelativePosition(Resize(130, 0, 180, 20));
btnBP->setRelativePosition(Resize(195, 0, 245, 20));
btnM2->setRelativePosition(Resize(260, 0, 310, 20));
}
btnEP->setRelativePosition(Resize(320, 0, 370, 20));
btnShuffle->setRelativePosition(Resize(0, 0, 50, 20));
}
btnSpectatorSwap->setRelativePosition(Resize(205, 100, 295, 135)); btnSpectatorSwap->setRelativePosition(Resize(205, 100, 295, 135));
btnChainAlways->setRelativePosition(Resize(205, 140, 295, 175)); btnChainAlways->setRelativePosition(Resize(205, 140, 295, 175));
btnChainIgnore->setRelativePosition(Resize(205, 100, 295, 135)); btnChainIgnore->setRelativePosition(Resize(205, 100, 295, 135));
......
...@@ -48,6 +48,7 @@ struct Config { ...@@ -48,6 +48,7 @@ struct Config {
struct DuelInfo { struct DuelInfo {
bool isStarted; bool isStarted;
bool isReplay; bool isReplay;
bool isOldReplay;
bool isReplaySkiping; bool isReplaySkiping;
bool isFirst; bool isFirst;
bool isTag; bool isTag;
...@@ -134,6 +135,7 @@ public: ...@@ -134,6 +135,7 @@ public:
const wchar_t* LocalName(int local_player); const wchar_t* LocalName(int local_player);
void UpdateDuelParam(); void UpdateDuelParam();
int GetMasterRule(uint32 param, uint32 forbidden, int* truerule = 0); int GetMasterRule(uint32 param, uint32 forbidden, int* truerule = 0);
void SetPhaseButtons();
bool HasFocus(EGUI_ELEMENT_TYPE type) const { bool HasFocus(EGUI_ELEMENT_TYPE type) const {
irr::gui::IGUIElement* focus = env->getFocus(); irr::gui::IGUIElement* focus = env->getFocus();
...@@ -170,7 +172,7 @@ public: ...@@ -170,7 +172,7 @@ public:
unsigned short linePattern; unsigned short linePattern;
int waitFrame; int waitFrame;
int signalFrame; int signalFrame;
int actionParam; int saveReplay;
const wchar_t* showingtext; const wchar_t* showingtext;
int showcard; int showcard;
int showcardcode; int showcardcode;
...@@ -309,6 +311,7 @@ public: ...@@ -309,6 +311,7 @@ public:
irr::gui::IGUIWindow* wReplay; irr::gui::IGUIWindow* wReplay;
irr::gui::IGUIListBox* lstReplayList; irr::gui::IGUIListBox* lstReplayList;
irr::gui::IGUIStaticText* stReplayInfo; irr::gui::IGUIStaticText* stReplayInfo;
irr::gui::IGUICheckBox* chkYrp;
irr::gui::IGUIButton* btnLoadReplay; irr::gui::IGUIButton* btnLoadReplay;
irr::gui::IGUIButton* btnReplayCancel; irr::gui::IGUIButton* btnReplayCancel;
irr::gui::IGUIEditBox* ebRepStartTurn; irr::gui::IGUIEditBox* ebRepStartTurn;
......
...@@ -274,6 +274,8 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -274,6 +274,8 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
if(!ReplayMode::cur_replay.OpenReplay(mainGame->lstReplayList->getListItem(mainGame->lstReplayList->getSelected()))) if(!ReplayMode::cur_replay.OpenReplay(mainGame->lstReplayList->getListItem(mainGame->lstReplayList->getSelected())))
break; break;
} }
if(mainGame->chkYrp->isChecked() && !ReplayMode::cur_replay.LoadYrp())
break;
mainGame->imgCard->setImage(imageManager.tCover[0]); mainGame->imgCard->setImage(imageManager.tCover[0]);
mainGame->wCardImg->setVisible(true); mainGame->wCardImg->setVisible(true);
mainGame->wInfos->setVisible(true); mainGame->wInfos->setVisible(true);
...@@ -393,6 +395,11 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -393,6 +395,11 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
repinfo.append(infobuf); repinfo.append(infobuf);
mainGame->ebRepStartTurn->setText(L"1"); mainGame->ebRepStartTurn->setText(L"1");
mainGame->SetStaticText(mainGame->stReplayInfo, 180, mainGame->guiFont, (wchar_t*)repinfo.c_str()); mainGame->SetStaticText(mainGame->stReplayInfo, 180, mainGame->guiFont, (wchar_t*)repinfo.c_str());
if(ReplayMode::cur_replay.pheader.id == 0x31707279) {
mainGame->chkYrp->setChecked(false);
mainGame->chkYrp->setEnabled(false);
} else
mainGame->chkYrp->setEnabled(true);
break; break;
} }
} }
......
...@@ -215,6 +215,9 @@ public: ...@@ -215,6 +215,9 @@ public:
#define STOC_HS_PLAYER_CHANGE 0x21 #define STOC_HS_PLAYER_CHANGE 0x21
#define STOC_HS_WATCH_CHANGE 0x22 #define STOC_HS_WATCH_CHANGE 0x22
#define STOC_NEW_REPLAY 0x30
#define PLAYERCHANGE_OBSERVE 0x8 #define PLAYERCHANGE_OBSERVE 0x8
#define PLAYERCHANGE_READY 0x9 #define PLAYERCHANGE_READY 0x9
#define PLAYERCHANGE_NOTREADY 0xa #define PLAYERCHANGE_NOTREADY 0xa
......
#include "replay_mode.h"
#include "duelclient.h"
#include "game.h"
#include "single_mode.h"
#include "../ocgcore/duel.h"
#include "../ocgcore/field.h"
#include "../ocgcore/mtrandom.h"
namespace ygo {
bool ReplayMode::ReadReplayResponse() {
unsigned char resp[64];
bool result = cur_replay.ReadNextResponse(resp);
if (result)
set_responseb(pduel, resp);
return result;
}
int ReplayMode::OldReplayThread(void* param) {
const ReplayHeader& rh = cur_replay.pheader;
mainGame->dInfo.isFirst = true;
mainGame->dInfo.isTag = !!(rh.flag & REPLAY_TAG);
mainGame->dInfo.isSingleMode = !!(rh.flag & REPLAY_SINGLE_MODE);
mainGame->dInfo.lua64 = true;
mainGame->dInfo.tag_player[0] = false;
mainGame->dInfo.tag_player[1] = false;
if (mainGame->dInfo.isSingleMode) {
set_script_reader((script_reader)SingleMode::ScriptReader);
set_card_reader((card_reader)DataManager::CardReader);
set_message_handler((message_handler)MessageHandler);
}
else {
set_script_reader(default_script_reader);
set_card_reader((card_reader)DataManager::CardReader);
set_message_handler((message_handler)MessageHandler);
}
if (!StartDuel()) {
EndDuel();
return 0;
}
mainGame->dInfo.isStarted = true;
mainGame->dInfo.isReplay = true;
mainGame->dInfo.isOldReplay = true;
mainGame->dInfo.isReplaySkiping = (skip_turn > 0);
char engineBuffer[0x1000];
is_continuing = true;
skip_step = 0;
if (mainGame->dInfo.isSingleMode) {
int len = get_message(pduel, (byte*)engineBuffer);
if (len > 0)
is_continuing = ReplayAnalyze(engineBuffer, len);
}
else {
ReplayRefreshDeck(0);
ReplayRefreshDeck(1);
ReplayRefreshExtra(0);
ReplayRefreshExtra(1);
}
exit_pending = false;
current_step = 0;
if (mainGame->dInfo.isReplaySkiping)
mainGame->gMutex.Lock();
while (is_continuing && !exit_pending) {
int result = process(pduel);
int len = result & 0xffff;
/*int flag = result >> 16;*/
if (len > 0) {
get_message(pduel, (byte*)engineBuffer);
is_continuing = ReplayAnalyze(engineBuffer, len);
if (is_restarting) {
is_restarting = false;
int step = current_step - 1;
if (step < 0)
step = 0;
if (mainGame->dInfo.isSingleMode) {
is_continuing = true;
skip_step = 0;
int len = get_message(pduel, (byte*)engineBuffer);
if (len > 0) {
mainGame->gMutex.Unlock();
is_continuing = ReplayAnalyze(engineBuffer, len);
mainGame->gMutex.Lock();
}
}
if (step == 0) {
Pause(true, false);
mainGame->dInfo.isStarted = true;
mainGame->dInfo.isReplaySkiping = false;
mainGame->dField.RefreshAllCards();
mainGame->gMutex.Unlock();
}
skip_step = step;
current_step = 0;
}
}
}
if (mainGame->dInfo.isReplaySkiping) {
mainGame->dInfo.isReplaySkiping = false;
mainGame->dField.RefreshAllCards();
mainGame->gMutex.Unlock();
}
EndDuel();
return 0;
}
bool ReplayMode::StartDuel() {
const ReplayHeader& rh = cur_replay.pheader;
mtrandom rnd;
int seed = rh.seed;
rnd.reset(seed);
if (mainGame->dInfo.isTag) {
cur_replay.ReadName(mainGame->dInfo.hostname);
cur_replay.ReadName(mainGame->dInfo.hostname_tag);
cur_replay.ReadName(mainGame->dInfo.clientname_tag);
cur_replay.ReadName(mainGame->dInfo.clientname);
}
else {
cur_replay.ReadName(mainGame->dInfo.hostname);
cur_replay.ReadName(mainGame->dInfo.clientname);
}
pduel = create_duel(rnd.rand());
int start_lp = cur_replay.ReadInt32();
int start_hand = cur_replay.ReadInt32();
int draw_count = cur_replay.ReadInt32();
int opt = cur_replay.ReadInt32();
int duel_rule = opt >> 16;
int rule = opt >> 16; //backwards compatibility with master rule replays
if (rule)
switch (rule) {
case 1: {
opt |= MASTER_RULE_1;
break;
}
case 2: {
opt |= MASTER_RULE_2;
break;
}
case 3: {
opt |= MASTER_RULE_3;
break;
}
case 4: {
opt |= MASTER_RULE_4;
break;
}
}
//pre mr4 replay compatibility
if (opt & DUEL_OBSOLETE_RULING) {
opt &= ~DUEL_OBSOLETE_RULING;
opt |= MASTER_RULE_1;
}
else if (!(opt & 0xff80))
opt |= MASTER_RULE_3;
mainGame->dInfo.duel_field = 2;
if ((opt & DUEL_PZONE) && (opt & DUEL_SEPARATE_PZONE) && (opt & DUEL_EMZONE))
mainGame->dInfo.duel_field = 5;
else if (opt & DUEL_EMZONE)
mainGame->dInfo.duel_field = 4;
else if (opt & DUEL_PZONE)
mainGame->dInfo.duel_field = 3;
mainGame->dInfo.extraval = !!(opt & SPEED_DUEL);
// reset master rule 4 phase button position
mainGame->wPhase->setRelativePosition(mainGame->Resize(480, 310, 855, 330));
if (mainGame->dInfo.extraval) {
if (mainGame->dInfo.duel_field >= 4) {
mainGame->wPhase->setRelativePosition(mainGame->Resize(480, 290, 855, 350));
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnDP->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnSP->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnM1->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnBP->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnM2->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnEP->setRelativePosition(mainGame->Resize(310, 0, 360, 20));
}
else {
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnDP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnSP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(130, 0, 180, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(195, 0, 245, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
mainGame->btnEP->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
}
}
else {
mainGame->btnDP->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
if (mainGame->dInfo.duel_field >= 4) {
mainGame->btnSP->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
}
else {
mainGame->btnSP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(130, 0, 180, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(195, 0, 245, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
}
mainGame->btnEP->setRelativePosition(mainGame->Resize(320, 0, 370, 20));
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
}
set_player_info(pduel, 0, start_lp, start_hand, draw_count);
set_player_info(pduel, 1, start_lp, start_hand, draw_count);
mainGame->dInfo.lp[0] = start_lp;
mainGame->dInfo.lp[1] = start_lp;
mainGame->dInfo.startlp = start_lp;
myswprintf(mainGame->dInfo.strLP[0], L"%d", mainGame->dInfo.lp[0]);
myswprintf(mainGame->dInfo.strLP[1], L"%d", mainGame->dInfo.lp[1]);
mainGame->dInfo.turn = 0;
if (!mainGame->dInfo.isSingleMode) {
if (!(opt & DUEL_TAG_MODE)) {
int main = cur_replay.ReadInt32();
for (int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
int extra = cur_replay.ReadInt32();
for (int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(0, main, extra);
main = cur_replay.ReadInt32();
for (int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
extra = cur_replay.ReadInt32();
for (int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(1, main, extra);
}
else {
int main = cur_replay.ReadInt32();
for (int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
int extra = cur_replay.ReadInt32();
for (int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(0, main, extra);
main = cur_replay.ReadInt32();
for (int i = 0; i < main; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 0, LOCATION_DECK);
extra = cur_replay.ReadInt32();
for (int i = 0; i < extra; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 0, LOCATION_EXTRA);
main = cur_replay.ReadInt32();
for (int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
extra = cur_replay.ReadInt32();
for (int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(1, main, extra);
main = cur_replay.ReadInt32();
for (int i = 0; i < main; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 1, LOCATION_DECK);
extra = cur_replay.ReadInt32();
for (int i = 0; i < extra; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 1, LOCATION_EXTRA);
}
}
else {
char filename[256];
size_t slen = cur_replay.ReadInt16();
cur_replay.ReadData(filename, slen);
filename[slen] = 0;
if (!preload_script(pduel, filename, slen)) {
return false;
}
}
start_duel(pduel, opt);
return true;
}
bool ReplayMode::ReplayAnalyze(char* msg, unsigned int len) {
char* pbuf = msg;
int player, count;
is_restarting = false;
while (pbuf - msg < (int)len) {
if (is_closing)
return false;
if (is_restarting) {
//is_restarting = false;
return true;
}
if (is_swapping) {
mainGame->gMutex.Lock();
mainGame->dField.ReplaySwap();
mainGame->gMutex.Unlock();
is_swapping = false;
}
char* offset = pbuf;
bool pauseable = true;
mainGame->dInfo.curMsg = BufferIO::ReadUInt8(pbuf);
switch (mainGame->dInfo.curMsg) {
case MSG_RETRY: {
if (mainGame->dInfo.isReplaySkiping) {
mainGame->dInfo.isReplaySkiping = false;
mainGame->dField.RefreshAllCards();
mainGame->gMutex.Unlock();
}
mainGame->gMutex.Lock();
mainGame->stMessage->setText(L"Error occurs.");
mainGame->PopupElement(mainGame->wMessage);
mainGame->gMutex.Unlock();
mainGame->actionSignal.Reset();
mainGame->actionSignal.Wait();
return false;
}
case MSG_HINT: {
pbuf += (mainGame->dInfo.lua64) ? 10 : 6;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_WIN: {
if (mainGame->dInfo.isReplaySkiping) {
mainGame->dInfo.isReplaySkiping = false;
mainGame->dField.RefreshAllCards();
mainGame->gMutex.Unlock();
}
pbuf += 2;
DuelClient::ClientAnalyze(offset, pbuf - offset);
return false;
}
case MSG_SELECT_BATTLECMD: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * (mainGame->dInfo.lua64) ? 15 : 11;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8 + 2;
ReplayRefresh();
return ReadReplayResponse();
}
case MSG_SELECT_IDLECMD: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * (mainGame->dInfo.lua64) ? 15 : 11 + 3;
ReplayRefresh();
return ReadReplayResponse();
}
case MSG_SELECT_EFFECTYN: {
player = BufferIO::ReadInt8(pbuf);
pbuf += (mainGame->dInfo.lua64) ? 16 : 12;
return ReadReplayResponse();
}
case MSG_SELECT_YESNO: {
player = BufferIO::ReadInt8(pbuf);
pbuf += (mainGame->dInfo.lua64) ? 8 : 4;
return ReadReplayResponse();
}
case MSG_SELECT_OPTION: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * (mainGame->dInfo.lua64) ? 8 : 4;
return ReadReplayResponse();
}
case MSG_SELECT_CARD:
case MSG_SELECT_TRIBUTE: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 3;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8;
return ReadReplayResponse();
}
case MSG_SELECT_UNSELECT_CARD: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 4;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8;
return ReadReplayResponse();
}
case MSG_SELECT_CHAIN: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += 10 + count * (mainGame->dInfo.lua64) ? 17 : 13;
return ReadReplayResponse();
}
case MSG_SELECT_PLACE:
case MSG_SELECT_DISFIELD: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
return ReadReplayResponse();
}
case MSG_SELECT_POSITION: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
return ReadReplayResponse();
}
case MSG_SELECT_COUNTER: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 4;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 9;
return ReadReplayResponse();
}
case MSG_SELECT_SUM: {
pbuf++;
player = BufferIO::ReadInt8(pbuf);
pbuf += 6;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 11;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 11;
return ReadReplayResponse();
}
case MSG_SORT_CARD:
case MSG_SORT_CHAIN: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
return ReadReplayResponse();
}
case MSG_CONFIRM_DECKTOP: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_CONFIRM_EXTRATOP: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_CONFIRM_CARDS: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_SHUFFLE_DECK: {
player = BufferIO::ReadInt8(pbuf);
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefreshDeck(player);
break;
}
case MSG_SHUFFLE_HAND: {
/*int oplayer = */BufferIO::ReadInt8(pbuf);
int count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_SHUFFLE_EXTRA: {
/*int oplayer = */BufferIO::ReadInt8(pbuf);
int count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_REFRESH_DECK: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_SWAP_GRAVE_DECK: {
player = BufferIO::ReadInt8(pbuf);
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefreshGrave(player);
break;
}
case MSG_REVERSE_DECK: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefreshDeck(0);
ReplayRefreshDeck(1);
break;
}
case MSG_DECK_TOP: {
pbuf += 6;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_SHUFFLE_SET_CARD: {
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_NEW_TURN: {
if (skip_turn) {
skip_turn--;
if (skip_turn == 0) {
mainGame->dInfo.isReplaySkiping = false;
mainGame->dField.RefreshAllCards();
mainGame->gMutex.Unlock();
}
}
player = BufferIO::ReadInt8(pbuf);
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_NEW_PHASE: {
pbuf += 2;
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
break;
}
case MSG_MOVE: {
int pc = pbuf[4];
int pl = pbuf[5];
/*int ps = pbuf[6];*/
/*int pp = pbuf[7];*/
int cc = pbuf[8];
int cl = pbuf[9];
int cs = pbuf[10];
/*int cp = pbuf[11];*/
pbuf += 16;
DuelClient::ClientAnalyze(offset, pbuf - offset);
if (cl && !(cl & 0x80) && (pl != cl || pc != cc))
ReplayRefreshSingle(cc, cl, cs);
break;
}
case MSG_POS_CHANGE: {
pbuf += 9;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_SET: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_SWAP: {
pbuf += 16;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_FIELD_DISABLED: {
pbuf += 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_SUMMONING: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_SUMMONED: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
break;
}
case MSG_SPSUMMONING: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_SPSUMMONED: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
break;
}
case MSG_FLIPSUMMONING: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_FLIPSUMMONED: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
break;
}
case MSG_CHAINING: {
pbuf += (mainGame->dInfo.lua64) ? 20 : 16;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_CHAINED: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
break;
}
case MSG_CHAIN_SOLVING: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_CHAIN_SOLVED: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
pauseable = false;
break;
}
case MSG_CHAIN_END: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
pauseable = false;
break;
}
case MSG_CHAIN_NEGATED: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_CHAIN_DISABLED: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_CARD_SELECTED:
case MSG_RANDOM_SELECTED: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_BECOME_TARGET: {
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_DRAW: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_DAMAGE: {
pbuf += 5;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_RECOVER: {
pbuf += 5;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_EQUIP: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_LPUPDATE: {
pbuf += 5;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_UNEQUIP: {
pbuf += 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_CARD_TARGET: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_CANCEL_TARGET: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_PAY_LPCOST: {
pbuf += 5;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_ADD_COUNTER: {
pbuf += 7;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_REMOVE_COUNTER: {
pbuf += 7;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_ATTACK: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_BATTLE: {
pbuf += 26;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_ATTACK_DISABLED: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_DAMAGE_STEP_START: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
pauseable = false;
break;
}
case MSG_DAMAGE_STEP_END: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
pauseable = false;
break;
}
case MSG_MISSED_EFFECT: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_TOSS_COIN: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_TOSS_DICE: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_ROCK_PAPER_SCISSORS: {
player = BufferIO::ReadInt8(pbuf);
return ReadReplayResponse();
}
case MSG_HAND_RES: {
pbuf += 1;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_ANNOUNCE_RACE: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
return ReadReplayResponse();
}
case MSG_ANNOUNCE_ATTRIB: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
return ReadReplayResponse();
}
case MSG_ANNOUNCE_CARD: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 4;
return ReadReplayResponse();
}
case MSG_ANNOUNCE_NUMBER:
case MSG_ANNOUNCE_CARD_FILTER: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += (mainGame->dInfo.lua64) ? 8 : 4 * count;
return ReadReplayResponse();
}
case MSG_CARD_HINT: {
pbuf += (mainGame->dInfo.lua64) ? 13 : 9;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_PLAYER_HINT: {
pbuf += (mainGame->dInfo.lua64) ? 10 : 6;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_MATCH_KILL: {
pbuf += 4;
break;
}
case MSG_TAG_SWAP: {
player = pbuf[0];
pbuf += pbuf[2] * 4 + pbuf[4] * 4 + 9;
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefreshDeck(player);
ReplayRefreshExtra(player);
break;
}
case MSG_RELOAD_FIELD: {
pbuf++;
for (int p = 0; p < 2; ++p) {
pbuf += 4;
for (int seq = 0; seq < 7; ++seq) {
int val = BufferIO::ReadInt8(pbuf);
if (val)
pbuf += 2;
}
for (int seq = 0; seq < 8; ++seq) {
int val = BufferIO::ReadInt8(pbuf);
if (val)
pbuf++;
}
pbuf += 6;
}
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayReload();
mainGame->dField.RefreshAllCards();
break;
}
case MSG_AI_NAME: {
int len = BufferIO::ReadInt16(pbuf);
pbuf += len + 1;
break;
}
case MSG_SHOW_HINT: {
int len = BufferIO::ReadInt16(pbuf);
pbuf += len + 1;
break;
}
}
if (pauseable) {
current_step++;
if (skip_step) {
skip_step--;
if (skip_step == 0) {
Pause(true, false);
mainGame->dInfo.isStarted = true;
mainGame->dInfo.isReplaySkiping = false;
mainGame->dField.RefreshAllCards();
mainGame->gMutex.Unlock();
}
}
if (is_pausing) {
is_paused = true;
mainGame->actionSignal.Reset();
mainGame->actionSignal.Wait();
is_paused = false;
}
}
}
return true;
}
void ReplayMode::ReplayRefresh(int flag) {
unsigned char queryBuffer[0x4000];
/*int len = */query_field_card(pduel, 0, LOCATION_MZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_MZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_MZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_MZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_SZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_SZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_SZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_SZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_HAND, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_HAND, (char*)queryBuffer);
}
void ReplayMode::ReplayRefreshHand(int player, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_HAND, (char*)queryBuffer);
}
void ReplayMode::ReplayRefreshGrave(int player, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_GRAVE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_GRAVE, (char*)queryBuffer);
}
void ReplayMode::ReplayRefreshDeck(int player, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_DECK, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_DECK, (char*)queryBuffer);
}
void ReplayMode::ReplayRefreshExtra(int player, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_EXTRA, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_EXTRA, (char*)queryBuffer);
}
void ReplayMode::ReplayRefreshSingle(int player, int location, int sequence, int flag) {
unsigned char queryBuffer[0x4000];
/*int len = */query_card(pduel, player, location, sequence, flag, queryBuffer, 0);
mainGame->dField.UpdateCard(mainGame->LocalPlayer(player), location, sequence, (char*)queryBuffer);
}
void ReplayMode::ReplayReload() {
unsigned char queryBuffer[0x4000];
unsigned int flag = 0xffdfff;
/*int len = */query_field_card(pduel, 0, LOCATION_MZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_MZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_MZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_MZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_SZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_SZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_SZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_SZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_HAND, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_HAND, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_DECK, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_DECK, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_DECK, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_DECK, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_EXTRA, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_EXTRA, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_EXTRA, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_EXTRA, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_GRAVE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_GRAVE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_GRAVE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_GRAVE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_REMOVED, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_REMOVED, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_REMOVED, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_REMOVED, (char*)queryBuffer);
}
int ReplayMode::MessageHandler(long fduel, int type) {
if (!enable_log)
return 0;
char msgbuf[1024];
get_log_message(fduel, (byte*)msgbuf);
mainGame->AddDebugMsg(msgbuf);
return 0;
}
}
\ No newline at end of file
#include "replay.h" #include "replay.h"
#include "../ocgcore/ocgapi.h" #include "../ocgcore/ocgapi.h"
#include "../ocgcore/card.h" #include "../ocgcore/card.h"
#include "../ocgcore/field.h"
#include <algorithm> #include <algorithm>
#include "lzma/LzmaLib.h" #include "lzma/LzmaLib.h"
namespace ygo { namespace ygo {
ReplayPacket::ReplayPacket(char * buf, int len) {
message = BufferIO::ReadInt8(buf);
length = len;
memcpy(data, buf, length);
}
ReplayPacket::ReplayPacket(int msg, char * buf, int len) {
message = msg;
length = len;
memcpy(data, buf, length);
}
void ReplayPacket::Set(int msg, char * buf, int len) {
message = msg;
length = len;
memcpy(data, buf, length);
}
Replay::Replay() { Replay::Replay() {
is_recording = false; is_recording = false;
is_replaying = false; is_replaying = false;
...@@ -16,25 +33,42 @@ Replay::~Replay() { ...@@ -16,25 +33,42 @@ Replay::~Replay() {
delete[] replay_data; delete[] replay_data;
delete[] comp_data; delete[] comp_data;
} }
void Replay::BeginRecord() { void Replay::BeginRecord(bool write) {
#ifdef _WIN32 #ifdef _WIN32
if(is_recording) if(is_recording && is_writing)
CloseHandle(recording_fp); CloseHandle(recording_fp);
recording_fp = CreateFileW(L"./replay/_LastReplay.yrp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL); is_writing = write;
if(is_writing) {
recording_fp = CreateFileW(L"./replay/_LastReplay.yrpX", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
if(recording_fp == INVALID_HANDLE_VALUE) if(recording_fp == INVALID_HANDLE_VALUE)
return; return;
}
#else #else
if(is_recording) if(is_recording && is_writing)
fclose(fp); fclose(fp);
fp = fopen("./replay/_LastReplay.yrp", "wb"); is_writing = write;
if(is_writing) {
fp = fopen("./replay/_LastReplay.yrpX", "wb");
if(!fp) if(!fp)
return; return;
}
#endif #endif
pdata = replay_data; pdata = replay_data;
is_recording = true; is_recording = true;
} }
void Replay::WritePacket(ReplayPacket p) {
WriteInt8(p.message, false);
WriteInt32(p.length, false);
WriteData((char*)p.data, p.length);
}
void Replay::WriteStream(std::vector<ReplayPacket> stream) {
if(stream.size())
for(auto it = stream.begin(); it != stream.end(); it++)
WritePacket((*it));
}
void Replay::WriteHeader(ReplayHeader& header) { void Replay::WriteHeader(ReplayHeader& header) {
pheader = header; pheader = header;
if(!is_writing) return;
#ifdef _WIN32 #ifdef _WIN32
DWORD size; DWORD size;
WriteFile(recording_fp, &header, sizeof(header), &size, NULL); WriteFile(recording_fp, &header, sizeof(header), &size, NULL);
...@@ -48,6 +82,7 @@ void Replay::WriteData(const void* data, unsigned int length, bool flush) { ...@@ -48,6 +82,7 @@ void Replay::WriteData(const void* data, unsigned int length, bool flush) {
return; return;
memcpy(pdata, data, length); memcpy(pdata, data, length);
pdata += length; pdata += length;
if(!is_writing) return;
#ifdef _WIN32 #ifdef _WIN32
DWORD size; DWORD size;
WriteFile(recording_fp, data, length, &size, NULL); WriteFile(recording_fp, data, length, &size, NULL);
...@@ -62,6 +97,7 @@ void Replay::WriteInt32(int data, bool flush) { ...@@ -62,6 +97,7 @@ void Replay::WriteInt32(int data, bool flush) {
return; return;
*((int*)(pdata)) = data; *((int*)(pdata)) = data;
pdata += 4; pdata += 4;
if(!is_writing) return;
#ifdef _WIN32 #ifdef _WIN32
DWORD size; DWORD size;
WriteFile(recording_fp, &data, sizeof(int), &size, NULL); WriteFile(recording_fp, &data, sizeof(int), &size, NULL);
...@@ -76,6 +112,7 @@ void Replay::WriteInt16(short data, bool flush) { ...@@ -76,6 +112,7 @@ void Replay::WriteInt16(short data, bool flush) {
return; return;
*((short*)(pdata)) = data; *((short*)(pdata)) = data;
pdata += 2; pdata += 2;
if(!is_writing) return;
#ifdef _WIN32 #ifdef _WIN32
DWORD size; DWORD size;
WriteFile(recording_fp, &data, sizeof(short), &size, NULL); WriteFile(recording_fp, &data, sizeof(short), &size, NULL);
...@@ -90,6 +127,7 @@ void Replay::WriteInt8(char data, bool flush) { ...@@ -90,6 +127,7 @@ void Replay::WriteInt8(char data, bool flush) {
return; return;
*pdata = data; *pdata = data;
pdata++; pdata++;
if(!is_writing) return;
#ifdef _WIN32 #ifdef _WIN32
DWORD size; DWORD size;
WriteFile(recording_fp, &data, sizeof(char), &size, NULL); WriteFile(recording_fp, &data, sizeof(char), &size, NULL);
...@@ -102,14 +140,16 @@ void Replay::WriteInt8(char data, bool flush) { ...@@ -102,14 +140,16 @@ void Replay::WriteInt8(char data, bool flush) {
void Replay::Flush() { void Replay::Flush() {
if(!is_recording) if(!is_recording)
return; return;
if(!is_writing) return;
#ifdef _WIN32 #ifdef _WIN32
#else #else
fflush(fp); fflush(fp);
#endif #endif
} }
void Replay::EndRecord() { void Replay::EndRecord(size_t size) {
if(!is_recording) if(!is_recording)
return; return;
if(is_writing)
#ifdef _WIN32 #ifdef _WIN32
CloseHandle(recording_fp); CloseHandle(recording_fp);
#else #else
...@@ -118,13 +158,13 @@ void Replay::EndRecord() { ...@@ -118,13 +158,13 @@ void Replay::EndRecord() {
pheader.datasize = pdata - replay_data; pheader.datasize = pdata - replay_data;
pheader.flag |= REPLAY_COMPRESSED; pheader.flag |= REPLAY_COMPRESSED;
size_t propsize = 5; size_t propsize = 5;
comp_size = 0x1000; comp_size = size;
LzmaCompress(comp_data, &comp_size, replay_data, pdata - replay_data, pheader.props, &propsize, 5, 1 << 24, 3, 0, 2, 32, 1); LzmaCompress(comp_data, &comp_size, replay_data, pdata - replay_data, pheader.props, &propsize, 5, 1 << 24, 3, 0, 2, 32, 1);
is_recording = false; is_recording = false;
} }
void Replay::SaveReplay(const wchar_t* name) { void Replay::SaveReplay(const wchar_t* name) {
wchar_t fname[256]; wchar_t fname[256];
myswprintf(fname, L"./replay/%ls.yrp", name); myswprintf(fname, L"./replay/%ls.yrpX", name);
#ifdef WIN32 #ifdef WIN32
fp = _wfopen(fname, L"wb"); fp = _wfopen(fname, L"wb");
#else #else
...@@ -161,7 +201,7 @@ bool Replay::OpenReplay(const wchar_t* name) { ...@@ -161,7 +201,7 @@ bool Replay::OpenReplay(const wchar_t* name) {
return false; return false;
fread(&pheader, sizeof(pheader), 1, fp); fread(&pheader, sizeof(pheader), 1, fp);
if(pheader.flag & REPLAY_COMPRESSED) { if(pheader.flag & REPLAY_COMPRESSED) {
comp_size = fread(comp_data, 1, 0x1000, fp); comp_size = fread(comp_data, 1, 0x20000, fp);
fclose(fp); fclose(fp);
replay_size = pheader.datasize; replay_size = pheader.datasize;
if(LzmaUncompress(replay_data, &replay_size, comp_data, &comp_size, pheader.props, 5) != SZ_OK) if(LzmaUncompress(replay_data, &replay_size, comp_data, &comp_size, pheader.props, 5) != SZ_OK)
...@@ -190,7 +230,23 @@ bool Replay::CheckReplay(const wchar_t* name) { ...@@ -190,7 +230,23 @@ bool Replay::CheckReplay(const wchar_t* name) {
ReplayHeader rheader; ReplayHeader rheader;
fread(&rheader, sizeof(ReplayHeader), 1, rfp); fread(&rheader, sizeof(ReplayHeader), 1, rfp);
fclose(rfp); fclose(rfp);
return rheader.id == 0x31707279 && rheader.version >= 0x12d0; return (rheader.id == 0x31707279 || rheader.id == 0x58707279) && rheader.version >= 0x12d0;
}
bool Replay::ReadNextPacket(ReplayPacket* packet) {
if (pdata - replay_data >= (int)replay_size)
return false;
packet->message = *pdata++;
packet->length = ReadInt32();
ReadData((char*)&packet->data, packet->length);
return true;
}
bool Replay::ReadStream(std::vector<ReplayPacket>* stream) {
stream->clear();
ReplayPacket p;
while (ReadNextPacket(&p)) {
stream->push_back(p);
}
return !!stream->size();
} }
bool Replay::ReadNextResponse(unsigned char resp[64]) { bool Replay::ReadNextResponse(unsigned char resp[64]) {
if(pdata - replay_data >= (int)replay_size) if(pdata - replay_data >= (int)replay_size)
...@@ -238,4 +294,31 @@ void Replay::Rewind() { ...@@ -238,4 +294,31 @@ void Replay::Rewind() {
pdata = replay_data; pdata = replay_data;
} }
bool Replay::LoadYrp() {
if (pheader.flag & REPLAY_NEWREPLAY) {
pdata += (4 + ((pheader.flag & REPLAY_TAG) ? 160 : 80));
ReplayPacket p;
while (ReadNextPacket(&p))
if (p.message == OLD_REPLAY_MODE) {
char* prep = (char*)p.data;
memcpy(&pheader, prep, sizeof(ReplayHeader));
prep += sizeof(ReplayHeader);
if(pheader.flag & REPLAY_COMPRESSED) {
comp_size = (size_t)(p.length - sizeof(ReplayHeader));
replay_size = pheader.datasize;
if (LzmaUncompress(replay_data, &replay_size, (unsigned char*)prep, &comp_size, pheader.props, 5) != SZ_OK)
return false;
} else {
comp_size = fread(replay_data, 1, 0x20000, fp);
fclose(fp);
replay_size = comp_size;
}
pdata = replay_data;
is_replaying = true;
return true;
}
}
return !(pheader.flag & REPLAY_NEWREPLAY);
}
} }
...@@ -11,6 +11,7 @@ namespace ygo { ...@@ -11,6 +11,7 @@ namespace ygo {
#define REPLAY_DECODED 0x4 #define REPLAY_DECODED 0x4
#define REPLAY_SINGLE_MODE 0x8 #define REPLAY_SINGLE_MODE 0x8
#define REPLAY_LUA64 0x10 #define REPLAY_LUA64 0x10
#define REPLAY_NEWREPLAY 0x20
struct ReplayHeader { struct ReplayHeader {
unsigned int id; unsigned int id;
...@@ -22,29 +23,44 @@ struct ReplayHeader { ...@@ -22,29 +23,44 @@ struct ReplayHeader {
unsigned char props[8]; unsigned char props[8];
}; };
class ReplayPacket {
public:
int message;
int length;
unsigned char data[0x2000];
ReplayPacket() {}
ReplayPacket(char * buf, int len);
ReplayPacket(int msg, char * buf, int len);
void Set(int msg, char * buf, int len);
};
class Replay { class Replay {
public: public:
Replay(); Replay();
~Replay(); ~Replay();
void BeginRecord(); void BeginRecord(bool write = true);
void WriteStream(std::vector<ReplayPacket> stream);
void WritePacket(ReplayPacket p);
void WriteHeader(ReplayHeader& header); void WriteHeader(ReplayHeader& header);
void WriteData(const void* data, unsigned int length, bool flush = true); void WriteData(const void* data, unsigned int length, bool flush = true);
void WriteInt32(int data, bool flush = true); void WriteInt32(int data, bool flush = true);
void WriteInt16(short data, bool flush = true); void WriteInt16(short data, bool flush = true);
void WriteInt8(char data, bool flush = true); void WriteInt8(char data, bool flush = true);
void Flush(); void Flush();
void EndRecord(); void EndRecord(size_t size = 0x20000);
void SaveReplay(const wchar_t* name); void SaveReplay(const wchar_t* name);
bool OpenReplay(const wchar_t* name); bool OpenReplay(const wchar_t* name);
static bool CheckReplay(const wchar_t* name); static bool CheckReplay(const wchar_t* name);
bool ReadNextPacket(ReplayPacket* packet);
bool ReadStream(std::vector<ReplayPacket>* stream);
bool ReadNextResponse(unsigned char resp[64]); bool ReadNextResponse(unsigned char resp[64]);
void ReadName(wchar_t* data); void ReadName(wchar_t* data);
void ReadHeader(ReplayHeader& header);
void ReadData(void* data, unsigned int length); void ReadData(void* data, unsigned int length);
int ReadInt32(); int ReadInt32();
short ReadInt16(); short ReadInt16();
char ReadInt8(); char ReadInt8();
void Rewind(); void Rewind();
bool LoadYrp();
FILE* fp; FILE* fp;
ReplayHeader pheader; ReplayHeader pheader;
...@@ -57,6 +73,7 @@ public: ...@@ -57,6 +73,7 @@ public:
size_t replay_size; size_t replay_size;
size_t comp_size; size_t comp_size;
bool is_recording; bool is_recording;
bool is_writing;
bool is_replaying; bool is_replaying;
}; };
......
...@@ -9,12 +9,14 @@ ...@@ -9,12 +9,14 @@
namespace ygo { namespace ygo {
long ReplayMode::pduel = 0; long ReplayMode::pduel = 0;
bool ReplayMode::yrp = false;
Replay ReplayMode::cur_replay; Replay ReplayMode::cur_replay;
std::vector<ReplayPacket> ReplayMode::current_stream;
bool ReplayMode::is_continuing = true; bool ReplayMode::is_continuing = true;
bool ReplayMode::is_closing = false; bool ReplayMode::is_closing = false;
bool ReplayMode::is_pausing = false; bool ReplayMode::is_pausing = false;
bool ReplayMode::is_paused = false; bool ReplayMode::is_paused = false;
bool ReplayMode::is_swaping = false; bool ReplayMode::is_swapping = false;
bool ReplayMode::is_restarting = false; bool ReplayMode::is_restarting = false;
bool ReplayMode::exit_pending = false; bool ReplayMode::exit_pending = false;
int ReplayMode::skip_turn = 0; int ReplayMode::skip_turn = 0;
...@@ -25,6 +27,10 @@ bool ReplayMode::StartReplay(int skipturn) { ...@@ -25,6 +27,10 @@ bool ReplayMode::StartReplay(int skipturn) {
skip_turn = skipturn; skip_turn = skipturn;
if(skip_turn < 0) if(skip_turn < 0)
skip_turn = 0; skip_turn = 0;
yrp = cur_replay.pheader.id == 0x31707279;
if(yrp)
Thread::NewThread(OldReplayThread, 0);
else
Thread::NewThread(ReplayThread, 0); Thread::NewThread(ReplayThread, 0);
return true; return true;
} }
...@@ -39,7 +45,7 @@ void ReplayMode::SwapField() { ...@@ -39,7 +45,7 @@ void ReplayMode::SwapField() {
if(is_paused) if(is_paused)
mainGame->dField.ReplaySwap(); mainGame->dField.ReplaySwap();
else else
is_swaping = true; is_swapping = true;
} }
void ReplayMode::Pause(bool is_pause, bool is_step) { void ReplayMode::Pause(bool is_pause, bool is_step) {
if(is_pause) if(is_pause)
...@@ -50,13 +56,6 @@ void ReplayMode::Pause(bool is_pause, bool is_step) { ...@@ -50,13 +56,6 @@ void ReplayMode::Pause(bool is_pause, bool is_step) {
mainGame->actionSignal.Set(); mainGame->actionSignal.Set();
} }
} }
bool ReplayMode::ReadReplayResponse() {
unsigned char resp[64];
bool result = cur_replay.ReadNextResponse(resp);
if(result)
set_responseb(pduel, resp);
return result;
}
int ReplayMode::ReplayThread(void* param) { int ReplayMode::ReplayThread(void* param) {
const ReplayHeader& rh = cur_replay.pheader; const ReplayHeader& rh = cur_replay.pheader;
mainGame->dInfo.isFirst = true; mainGame->dInfo.isFirst = true;
...@@ -65,62 +64,43 @@ int ReplayMode::ReplayThread(void* param) { ...@@ -65,62 +64,43 @@ int ReplayMode::ReplayThread(void* param) {
mainGame->dInfo.lua64 = !!(rh.flag & REPLAY_LUA64); mainGame->dInfo.lua64 = !!(rh.flag & REPLAY_LUA64);
mainGame->dInfo.tag_player[0] = false; mainGame->dInfo.tag_player[0] = false;
mainGame->dInfo.tag_player[1] = false; mainGame->dInfo.tag_player[1] = false;
if(mainGame->dInfo.isSingleMode) { if (mainGame->dInfo.isTag) {
set_script_reader((script_reader)SingleMode::ScriptReader); cur_replay.ReadName(mainGame->dInfo.hostname);
set_card_reader((card_reader)DataManager::CardReader); cur_replay.ReadName(mainGame->dInfo.hostname_tag);
set_message_handler((message_handler)MessageHandler); cur_replay.ReadName(mainGame->dInfo.clientname_tag);
} else { cur_replay.ReadName(mainGame->dInfo.clientname);
set_script_reader(default_script_reader);
set_card_reader((card_reader)DataManager::CardReader);
set_message_handler((message_handler)MessageHandler);
} }
if(!StartDuel()) { else {
cur_replay.ReadName(mainGame->dInfo.hostname);
cur_replay.ReadName(mainGame->dInfo.clientname);
}
int opt = cur_replay.ReadInt32();
mainGame->dInfo.duel_field = opt & 0xff;
mainGame->dInfo.extraval = (opt >> 8);
mainGame->SetPhaseButtons();
if(!cur_replay.ReadStream(&current_stream)) {
EndDuel(); EndDuel();
return 0; return 0;
} }
mainGame->dInfo.isStarted = true; mainGame->dInfo.isStarted = true;
mainGame->dInfo.isReplay = true; mainGame->dInfo.isReplay = true;
mainGame->dInfo.turn = 0;
mainGame->dInfo.isReplaySkiping = (skip_turn > 0); mainGame->dInfo.isReplaySkiping = (skip_turn > 0);
char engineBuffer[0x1000];
is_continuing = true; is_continuing = true;
skip_step = 0; skip_step = 0;
if(mainGame->dInfo.isSingleMode) {
int len = get_message(pduel, (byte*)engineBuffer);
if (len > 0)
is_continuing = ReplayAnalyze(engineBuffer, len);
} else {
ReplayRefreshDeck(0);
ReplayRefreshDeck(1);
ReplayRefreshExtra(0);
ReplayRefreshExtra(1);
}
exit_pending = false; exit_pending = false;
current_step = 0; current_step = 0;
if(mainGame->dInfo.isReplaySkiping) if(mainGame->dInfo.isReplaySkiping)
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
while (is_continuing && !exit_pending) { for(auto it = current_stream.begin(); is_continuing && !exit_pending && it != current_stream.end();) {
int result = process(pduel); is_continuing = ReplayAnalyze((*it));
int len = result & 0xffff;
/*int flag = result >> 16;*/
if (len > 0) {
get_message(pduel, (byte*)engineBuffer);
is_continuing = ReplayAnalyze(engineBuffer, len);
if(is_restarting) { if(is_restarting) {
it = current_stream.begin();
is_restarting = false; is_restarting = false;
int step = current_step - 1; int step = current_step - 1;
if(step < 0) if (step < 0)
step = 0; step = 0;
if(mainGame->dInfo.isSingleMode) { if (step == 0) {
is_continuing = true;
skip_step = 0;
int len = get_message(pduel, (byte*)engineBuffer);
if (len > 0) {
mainGame->gMutex.Unlock();
is_continuing = ReplayAnalyze(engineBuffer, len);
mainGame->gMutex.Lock();
}
}
if(step == 0) {
Pause(true, false); Pause(true, false);
mainGame->dInfo.isStarted = true; mainGame->dInfo.isStarted = true;
mainGame->dInfo.isReplaySkiping = false; mainGame->dInfo.isReplaySkiping = false;
...@@ -129,8 +109,8 @@ int ReplayMode::ReplayThread(void* param) { ...@@ -129,8 +109,8 @@ int ReplayMode::ReplayThread(void* param) {
} }
skip_step = step; skip_step = step;
current_step = 0; current_step = 0;
} } else
} it++;
} }
if(mainGame->dInfo.isReplaySkiping) { if(mainGame->dInfo.isReplaySkiping) {
mainGame->dInfo.isReplaySkiping = false; mainGame->dInfo.isReplaySkiping = false;
...@@ -140,162 +120,8 @@ int ReplayMode::ReplayThread(void* param) { ...@@ -140,162 +120,8 @@ int ReplayMode::ReplayThread(void* param) {
EndDuel(); EndDuel();
return 0; return 0;
} }
bool ReplayMode::StartDuel() {
const ReplayHeader& rh = cur_replay.pheader;
mtrandom rnd;
int seed = rh.seed;
rnd.reset(seed);
if(mainGame->dInfo.isTag) {
cur_replay.ReadName(mainGame->dInfo.hostname);
cur_replay.ReadName(mainGame->dInfo.hostname_tag);
cur_replay.ReadName(mainGame->dInfo.clientname_tag);
cur_replay.ReadName(mainGame->dInfo.clientname);
} else {
cur_replay.ReadName(mainGame->dInfo.hostname);
cur_replay.ReadName(mainGame->dInfo.clientname);
}
pduel = create_duel(rnd.rand());
int start_lp = cur_replay.ReadInt32();
int start_hand = cur_replay.ReadInt32();
int draw_count = cur_replay.ReadInt32();
int opt = cur_replay.ReadInt32();
int duel_rule = opt >> 16;
int rule = opt >> 16; //backwards compatibility with master rule replays
if(rule)
switch (rule) {
case 1: {
opt |= MASTER_RULE_1;
break;
}
case 2: {
opt |= MASTER_RULE_2;
break;
}
case 3: {
opt |= MASTER_RULE_3;
break;
}
case 4: {
opt |= MASTER_RULE_4;
break;
}
}
//pre mr4 replay compatibility
if(opt & DUEL_OBSOLETE_RULING) {
opt &= ~DUEL_OBSOLETE_RULING;
opt |= MASTER_RULE_1;
} else if (!(opt & 0xff80))
opt |= MASTER_RULE_3;
mainGame->dInfo.duel_field = 2;
if ((opt & DUEL_PZONE) && (opt & DUEL_SEPARATE_PZONE) && (opt & DUEL_EMZONE))
mainGame->dInfo.duel_field = 5;
else if (opt & DUEL_EMZONE)
mainGame->dInfo.duel_field = 4;
else if(opt & DUEL_PZONE)
mainGame->dInfo.duel_field = 3;
mainGame->dInfo.extraval = !!(opt & SPEED_DUEL);
// reset master rule 4 phase button position
mainGame->wPhase->setRelativePosition(mainGame->Resize(480, 310, 855, 330));
if(mainGame->dInfo.extraval) {
if(mainGame->dInfo.duel_field >= 4) {
mainGame->wPhase->setRelativePosition(mainGame->Resize(480, 290, 855, 350));
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnDP->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnSP->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnM1->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnBP->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnM2->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnEP->setRelativePosition(mainGame->Resize(310, 0, 360, 20));
} else {
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnDP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnSP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(130, 0, 180, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(195, 0, 245, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
mainGame->btnEP->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
}
} else {
mainGame->btnDP->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
if(mainGame->dInfo.duel_field >= 4) {
mainGame->btnSP->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
} else {
mainGame->btnSP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(130, 0, 180, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(195, 0, 245, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
}
mainGame->btnEP->setRelativePosition(mainGame->Resize(320, 0, 370, 20));
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
}
set_player_info(pduel, 0, start_lp, start_hand, draw_count);
set_player_info(pduel, 1, start_lp, start_hand, draw_count);
mainGame->dInfo.lp[0] = start_lp;
mainGame->dInfo.lp[1] = start_lp;
mainGame->dInfo.startlp = start_lp;
myswprintf(mainGame->dInfo.strLP[0], L"%d", mainGame->dInfo.lp[0]);
myswprintf(mainGame->dInfo.strLP[1], L"%d", mainGame->dInfo.lp[1]);
mainGame->dInfo.turn = 0;
if(!mainGame->dInfo.isSingleMode) {
if(!(opt & DUEL_TAG_MODE)) {
int main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
int extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(0, main, extra);
main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(1, main, extra);
} else {
int main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
int extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(0, main, extra);
main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 0, LOCATION_DECK);
extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 0, LOCATION_EXTRA);
main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(1, main, extra);
main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 1, LOCATION_DECK);
extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 1, LOCATION_EXTRA);
}
} else {
char filename[256];
size_t slen = cur_replay.ReadInt16();
cur_replay.ReadData(filename, slen);
filename[slen] = 0;
if(!preload_script(pduel, filename, slen)) {
return false;
}
}
start_duel(pduel, opt);
return true;
}
void ReplayMode::EndDuel() { void ReplayMode::EndDuel() {
if(yrp)
end_duel(pduel); end_duel(pduel);
if(!is_closing) { if(!is_closing) {
mainGame->actionSignal.Reset(); mainGame->actionSignal.Reset();
...@@ -309,6 +135,7 @@ void ReplayMode::EndDuel() { ...@@ -309,6 +135,7 @@ void ReplayMode::EndDuel() {
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
mainGame->dInfo.isStarted = false; mainGame->dInfo.isStarted = false;
mainGame->dInfo.isReplay = false; mainGame->dInfo.isReplay = false;
mainGame->dInfo.isOldReplay = false;
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
mainGame->closeDoneSignal.Reset(); mainGame->closeDoneSignal.Reset();
mainGame->closeSignal.Set(); mainGame->closeSignal.Set();
...@@ -323,21 +150,21 @@ void ReplayMode::EndDuel() { ...@@ -323,21 +150,21 @@ void ReplayMode::EndDuel() {
} }
} }
void ReplayMode::Restart(bool refresh) { void ReplayMode::Restart(bool refresh) {
if(yrp) {
end_duel(pduel); end_duel(pduel);
cur_replay.Rewind();
}
mainGame->dInfo.isStarted = false; mainGame->dInfo.isStarted = false;
mainGame->dInfo.turn = 0;
mainGame->dField.Clear(); mainGame->dField.Clear();
//mainGame->device->setEventReceiver(&mainGame->dField);
cur_replay.Rewind();
//mainGame->dInfo.isFirst = true;
mainGame->dInfo.tag_player[0] = false; mainGame->dInfo.tag_player[0] = false;
mainGame->dInfo.tag_player[1] = false; mainGame->dInfo.tag_player[1] = false;
if(!StartDuel()) { if (yrp && !StartDuel()) {
EndDuel(); EndDuel();
} }
if(refresh) { if(refresh) {
mainGame->dField.RefreshAllCards(); mainGame->dField.RefreshAllCards();
mainGame->dInfo.isStarted = true; mainGame->dInfo.isStarted = true;
//mainGame->dInfo.isReplay = true;
} }
skip_turn = 0; skip_turn = 0;
is_restarting = true; is_restarting = true;
...@@ -350,26 +177,21 @@ void ReplayMode::Undo() { ...@@ -350,26 +177,21 @@ void ReplayMode::Undo() {
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
Pause(false, false); Pause(false, false);
} }
bool ReplayMode::ReplayAnalyze(char* msg, unsigned int len) { bool ReplayMode::ReplayAnalyze(ReplayPacket p) {
char* pbuf = msg;
int player, count;
is_restarting = false; is_restarting = false;
while (pbuf - msg < (int)len) { while(true) {
if(is_closing) if(is_closing)
return false; return false;
if(is_restarting) { if(is_restarting)
//is_restarting = false; break;
return true; if(is_swapping) {
}
if(is_swaping) {
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
mainGame->dField.ReplaySwap(); mainGame->dField.ReplaySwap();
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
is_swaping = false; is_swapping = false;
} }
char* offset = pbuf;
bool pauseable = true; bool pauseable = true;
mainGame->dInfo.curMsg = BufferIO::ReadUInt8(pbuf); mainGame->dInfo.curMsg = p.message;
switch (mainGame->dInfo.curMsg) { switch (mainGame->dInfo.curMsg) {
case MSG_RETRY: { case MSG_RETRY: {
if(mainGame->dInfo.isReplaySkiping) { if(mainGame->dInfo.isReplaySkiping) {
...@@ -385,188 +207,40 @@ bool ReplayMode::ReplayAnalyze(char* msg, unsigned int len) { ...@@ -385,188 +207,40 @@ bool ReplayMode::ReplayAnalyze(char* msg, unsigned int len) {
mainGame->actionSignal.Wait(); mainGame->actionSignal.Wait();
return false; return false;
} }
case MSG_HINT: {
pbuf += (mainGame->dInfo.lua64) ? 10 : 6;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_WIN: { case MSG_WIN: {
if(mainGame->dInfo.isReplaySkiping) { if (mainGame->dInfo.isReplaySkiping) {
mainGame->dInfo.isReplaySkiping = false; mainGame->dInfo.isReplaySkiping = false;
mainGame->dField.RefreshAllCards(); mainGame->dField.RefreshAllCards();
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
} }
pbuf += 2; DuelClient::ClientAnalyze((char*)p.data, p.length);
DuelClient::ClientAnalyze(offset, pbuf - offset);
return false; return false;
} }
case MSG_SELECT_BATTLECMD: { case MSG_START:
player = BufferIO::ReadInt8(pbuf); case MSG_UPDATE_DATA:
count = BufferIO::ReadInt8(pbuf); case MSG_UPDATE_CARD:
pbuf += count * (mainGame->dInfo.lua64) ? 15 : 11; case MSG_SET:
count = BufferIO::ReadInt8(pbuf); case MSG_SWAP:
pbuf += count * 8 + 2; case MSG_FIELD_DISABLED:
ReplayRefresh(); case MSG_SUMMONING:
return ReadReplayResponse(); case MSG_SPSUMMONING:
} case MSG_FLIPSUMMONING:
case MSG_SELECT_IDLECMD: { case MSG_CHAIN_SOLVING:
player = BufferIO::ReadInt8(pbuf); case MSG_CHAIN_SOLVED:
count = BufferIO::ReadInt8(pbuf); case MSG_CHAIN_END:
pbuf += count * 7; case MSG_CARD_SELECTED:
count = BufferIO::ReadInt8(pbuf); case MSG_RANDOM_SELECTED:
pbuf += count * 7; case MSG_EQUIP:
count = BufferIO::ReadInt8(pbuf); case MSG_UNEQUIP:
pbuf += count * 7; case MSG_CARD_TARGET:
count = BufferIO::ReadInt8(pbuf); case MSG_CANCEL_TARGET:
pbuf += count * 7; case MSG_BATTLE:
count = BufferIO::ReadInt8(pbuf); case MSG_ATTACK_DISABLED:
pbuf += count * 7; case MSG_DAMAGE_STEP_START:
count = BufferIO::ReadInt8(pbuf); case MSG_DAMAGE_STEP_END:
pbuf += count * (mainGame->dInfo.lua64) ? 15 : 11 + 3; case MSG_TAG_SWAP:
ReplayRefresh(); case MSG_RELOAD_FIELD: {
return ReadReplayResponse(); pauseable = false;
}
case MSG_SELECT_EFFECTYN: {
player = BufferIO::ReadInt8(pbuf);
pbuf += (mainGame->dInfo.lua64) ? 16 : 12;
return ReadReplayResponse();
}
case MSG_SELECT_YESNO: {
player = BufferIO::ReadInt8(pbuf);
pbuf += (mainGame->dInfo.lua64) ? 8 : 4;
return ReadReplayResponse();
}
case MSG_SELECT_OPTION: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * (mainGame->dInfo.lua64) ? 8 : 4;
return ReadReplayResponse();
}
case MSG_SELECT_CARD:
case MSG_SELECT_TRIBUTE: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 3;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8;
return ReadReplayResponse();
}
case MSG_SELECT_UNSELECT_CARD: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 4;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8;
return ReadReplayResponse();
}
case MSG_SELECT_CHAIN: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += 10 + count * (mainGame->dInfo.lua64) ? 17 : 13;
return ReadReplayResponse();
}
case MSG_SELECT_PLACE:
case MSG_SELECT_DISFIELD: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
return ReadReplayResponse();
}
case MSG_SELECT_POSITION: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
return ReadReplayResponse();
}
case MSG_SELECT_COUNTER: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 4;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 9;
return ReadReplayResponse();
}
case MSG_SELECT_SUM: {
pbuf++;
player = BufferIO::ReadInt8(pbuf);
pbuf += 6;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 11;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 11;
return ReadReplayResponse();
}
case MSG_SORT_CARD:
case MSG_SORT_CHAIN: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
return ReadReplayResponse();
}
case MSG_CONFIRM_DECKTOP: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_CONFIRM_EXTRATOP: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_CONFIRM_CARDS: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_SHUFFLE_DECK: {
player = BufferIO::ReadInt8(pbuf);
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefreshDeck(player);
break;
}
case MSG_SHUFFLE_HAND: {
/*int oplayer = */BufferIO::ReadInt8(pbuf);
int count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_SHUFFLE_EXTRA: {
/*int oplayer = */BufferIO::ReadInt8(pbuf);
int count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_REFRESH_DECK: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_SWAP_GRAVE_DECK: {
player = BufferIO::ReadInt8(pbuf);
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefreshGrave(player);
break;
}
case MSG_REVERSE_DECK: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefreshDeck(0);
ReplayRefreshDeck(1);
break;
}
case MSG_DECK_TOP: {
pbuf += 6;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_SHUFFLE_SET_CARD: {
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break; break;
} }
case MSG_NEW_TURN: { case MSG_NEW_TURN: {
...@@ -578,335 +252,24 @@ bool ReplayMode::ReplayAnalyze(char* msg, unsigned int len) { ...@@ -578,335 +252,24 @@ bool ReplayMode::ReplayAnalyze(char* msg, unsigned int len) {
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
} }
} }
player = BufferIO::ReadInt8(pbuf);
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_NEW_PHASE: {
pbuf += 2;
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
break;
}
case MSG_MOVE: {
int pc = pbuf[4];
int pl = pbuf[5];
/*int ps = pbuf[6];*/
/*int pp = pbuf[7];*/
int cc = pbuf[8];
int cl = pbuf[9];
int cs = pbuf[10];
/*int cp = pbuf[11];*/
pbuf += 16;
DuelClient::ClientAnalyze(offset, pbuf - offset);
if(cl && !(cl & 0x80) && (pl != cl || pc != cc))
ReplayRefreshSingle(cc, cl, cs);
break;
}
case MSG_POS_CHANGE: {
pbuf += 9;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_SET: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_SWAP: {
pbuf += 16;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_FIELD_DISABLED: {
pbuf += 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_SUMMONING: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_SUMMONED: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
break;
}
case MSG_SPSUMMONING: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_SPSUMMONED: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
break;
}
case MSG_FLIPSUMMONING: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_FLIPSUMMONED: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
break;
}
case MSG_CHAINING: {
pbuf += (mainGame->dInfo.lua64) ? 20 : 16;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_CHAINED: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
break;
}
case MSG_CHAIN_SOLVING: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_CHAIN_SOLVED: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
pauseable = false;
break;
}
case MSG_CHAIN_END: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
pauseable = false;
break;
}
case MSG_CHAIN_NEGATED: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_CHAIN_DISABLED: {
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_CARD_SELECTED:
case MSG_RANDOM_SELECTED: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_BECOME_TARGET: {
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_DRAW: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_DAMAGE: {
pbuf += 5;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_RECOVER: {
pbuf += 5;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_EQUIP: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_LPUPDATE: {
pbuf += 5;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_UNEQUIP: {
pbuf += 4;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_CARD_TARGET: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_CANCEL_TARGET: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_PAY_LPCOST: {
pbuf += 5;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_ADD_COUNTER: {
pbuf += 7;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_REMOVE_COUNTER: {
pbuf += 7;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_ATTACK: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_BATTLE: {
pbuf += 26;
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_ATTACK_DISABLED: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
pauseable = false;
break;
}
case MSG_DAMAGE_STEP_START: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
pauseable = false;
break;
}
case MSG_DAMAGE_STEP_END: {
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefresh();
pauseable = false;
break;
}
case MSG_MISSED_EFFECT: {
pbuf += 8;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_TOSS_COIN: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_TOSS_DICE: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_ROCK_PAPER_SCISSORS: {
player = BufferIO::ReadInt8(pbuf);
return ReadReplayResponse();
}
case MSG_HAND_RES: {
pbuf += 1;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_ANNOUNCE_RACE: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
return ReadReplayResponse();
}
case MSG_ANNOUNCE_ATTRIB: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
return ReadReplayResponse();
}
case MSG_ANNOUNCE_CARD: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 4;
return ReadReplayResponse();
}
case MSG_ANNOUNCE_NUMBER:
case MSG_ANNOUNCE_CARD_FILTER: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += (mainGame->dInfo.lua64) ? 8 : 4 * count;
return ReadReplayResponse();
}
case MSG_CARD_HINT: {
pbuf += (mainGame->dInfo.lua64) ? 13 : 9;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_PLAYER_HINT: {
pbuf += (mainGame->dInfo.lua64) ? 10 : 6;
DuelClient::ClientAnalyze(offset, pbuf - offset);
break;
}
case MSG_MATCH_KILL: {
pbuf += 4;
break;
}
case MSG_TAG_SWAP: {
player = pbuf[0];
pbuf += pbuf[2] * 4 + pbuf[4] * 4 + 9;
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayRefreshDeck(player);
ReplayRefreshExtra(player);
break;
}
case MSG_RELOAD_FIELD: {
pbuf++;
for(int p = 0; p < 2; ++p) {
pbuf += 4;
for(int seq = 0; seq < 7; ++seq) {
int val = BufferIO::ReadInt8(pbuf);
if(val)
pbuf += 2;
}
for(int seq = 0; seq < 8; ++seq) {
int val = BufferIO::ReadInt8(pbuf);
if(val)
pbuf++;
}
pbuf += 6;
}
pbuf++;
DuelClient::ClientAnalyze(offset, pbuf - offset);
ReplayReload();
mainGame->dField.RefreshAllCards();
break; break;
} }
case MSG_AI_NAME: { case MSG_AI_NAME: {
char* pbuf =(char*) p.data;
char namebuf[128];
wchar_t wname[128];
int len = BufferIO::ReadInt16(pbuf); int len = BufferIO::ReadInt16(pbuf);
char* begin = pbuf;
pbuf += len + 1; pbuf += len + 1;
break; memcpy(namebuf, begin, len + 1);
} BufferIO::DecodeUTF8(namebuf, wname);
case MSG_SHOW_HINT: { BufferIO::CopyWStr(wname, mainGame->dInfo.clientname, 20);
int len = BufferIO::ReadInt16(pbuf); return true;
pbuf += len + 1;
break;
} }
case OLD_REPLAY_MODE:
return true;
} }
DuelClient::ClientAnalyze((char*)p.data, p.length);
if(pauseable) { if(pauseable) {
current_step++; current_step++;
if(skip_step) { if(skip_step) {
...@@ -926,88 +289,9 @@ bool ReplayMode::ReplayAnalyze(char* msg, unsigned int len) { ...@@ -926,88 +289,9 @@ bool ReplayMode::ReplayAnalyze(char* msg, unsigned int len) {
is_paused = false; is_paused = false;
} }
} }
break;
} }
return true; return true;
} }
void ReplayMode::ReplayRefresh(int flag) {
unsigned char queryBuffer[0x4000];
/*int len = */query_field_card(pduel, 0, LOCATION_MZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_MZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_MZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_MZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_SZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_SZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_SZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_SZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_HAND, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_HAND, (char*)queryBuffer);
}
void ReplayMode::ReplayRefreshHand(int player, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_HAND, (char*)queryBuffer);
}
void ReplayMode::ReplayRefreshGrave(int player, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_GRAVE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_GRAVE, (char*)queryBuffer);
}
void ReplayMode::ReplayRefreshDeck(int player, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_DECK, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_DECK, (char*)queryBuffer);
}
void ReplayMode::ReplayRefreshExtra(int player, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_EXTRA, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_EXTRA, (char*)queryBuffer);
}
void ReplayMode::ReplayRefreshSingle(int player, int location, int sequence, int flag) {
unsigned char queryBuffer[0x4000];
/*int len = */query_card(pduel, player, location, sequence, flag, queryBuffer, 0);
mainGame->dField.UpdateCard(mainGame->LocalPlayer(player), location, sequence, (char*)queryBuffer);
}
void ReplayMode::ReplayReload() {
unsigned char queryBuffer[0x4000];
unsigned int flag = 0xffdfff;
/*int len = */query_field_card(pduel, 0, LOCATION_MZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_MZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_MZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_MZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_SZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_SZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_SZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_SZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_HAND, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_HAND, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_DECK, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_DECK, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_DECK, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_DECK, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_EXTRA, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_EXTRA, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_EXTRA, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_EXTRA, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_GRAVE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_GRAVE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_GRAVE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_GRAVE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_REMOVED, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_REMOVED, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_REMOVED, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_REMOVED, (char*)queryBuffer);
}
int ReplayMode::MessageHandler(long fduel, int type) {
if(!enable_log)
return 0;
char msgbuf[1024];
get_log_message(fduel, (byte*)msgbuf);
mainGame->AddDebugMsg(msgbuf);
return 0;
}
} }
...@@ -12,12 +12,14 @@ namespace ygo { ...@@ -12,12 +12,14 @@ namespace ygo {
class ReplayMode { class ReplayMode {
private: private:
static long pduel; static long pduel;
static bool yrp;
static bool is_continuing; static bool is_continuing;
static bool is_closing; static bool is_closing;
static bool is_pausing; static bool is_pausing;
static bool is_paused; static bool is_paused;
static bool is_swaping; static bool is_swapping;
static bool is_restarting; static bool is_restarting;
static bool undo;
static bool exit_pending; static bool exit_pending;
static int skip_turn; static int skip_turn;
static int current_step; static int current_step;
...@@ -25,6 +27,7 @@ private: ...@@ -25,6 +27,7 @@ private:
public: public:
static Replay cur_replay; static Replay cur_replay;
static std::vector<ReplayPacket> ReplayMode::current_stream;
public: public:
static bool StartReplay(int skipturn); static bool StartReplay(int skipturn);
...@@ -33,10 +36,12 @@ public: ...@@ -33,10 +36,12 @@ public:
static void Pause(bool is_pause, bool is_step); static void Pause(bool is_pause, bool is_step);
static bool ReadReplayResponse(); static bool ReadReplayResponse();
static int ReplayThread(void* param); static int ReplayThread(void* param);
static int OldReplayThread(void* param);
static bool StartDuel(); static bool StartDuel();
static void EndDuel(); static void EndDuel();
static void Restart(bool refresh); static void Restart(bool refresh);
static void Undo(); static void Undo();
static bool ReplayAnalyze(ReplayPacket p);
static bool ReplayAnalyze(char* msg, unsigned int len); static bool ReplayAnalyze(char* msg, unsigned int len);
static void ReplayRefresh(int flag = 0xf81fff); static void ReplayRefresh(int flag = 0xf81fff);
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
namespace ygo { namespace ygo {
std::vector<ReplayPacket> SingleDuel::replay_stream;
SingleDuel::SingleDuel(bool is_match) { SingleDuel::SingleDuel(bool is_match) {
game_started = false; game_started = false;
match_mode = is_match; match_mode = is_match;
...@@ -187,6 +189,8 @@ void SingleDuel::LeaveGame(DuelPlayer* dp) { ...@@ -187,6 +189,8 @@ void SingleDuel::LeaveGame(DuelPlayer* dp) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
ReplayPacket p((char*)wbuf, 3);
replay_stream.push_back(p);
EndDuel(); EndDuel();
NetServer::SendPacketToPlayer(players[0], STOC_DUEL_END); NetServer::SendPacketToPlayer(players[0], STOC_DUEL_END);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
...@@ -398,11 +402,19 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -398,11 +402,19 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
rh.flag = REPLAY_LUA64; rh.flag = REPLAY_LUA64;
time_t seed = time(0); time_t seed = time(0);
rh.seed = seed; rh.seed = seed;
last_replay.BeginRecord(); last_replay.BeginRecord(false);
last_replay.WriteHeader(rh); last_replay.WriteHeader(rh);
rnd.reset(seed); rnd.reset(seed);
last_replay.WriteData(players[0]->name, 40, false); last_replay.WriteData(players[0]->name, 40, false);
last_replay.WriteData(players[1]->name, 40, false); last_replay.WriteData(players[1]->name, 40, false);
//records the replay with the new system
new_replay.BeginRecord();
rh.id = 0x58707279;
rh.flag |= REPLAY_NEWREPLAY;
new_replay.WriteHeader(rh);
new_replay.WriteData(players[0]->name, 40, false);
new_replay.WriteData(players[1]->name, 40);
replay_stream.clear();
if(!host_info.no_shuffle_deck) { if(!host_info.no_shuffle_deck) {
for(size_t i = pdeck[0].main.size() - 1; i > 0; --i) { for(size_t i = pdeck[0].main.size() - 1; i > 0; --i) {
int swap = rnd.real() * (i + 1); int swap = rnd.real() * (i + 1);
...@@ -427,6 +439,7 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -427,6 +439,7 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
opt |= DUEL_PSEUDO_SHUFFLE; opt |= DUEL_PSEUDO_SHUFFLE;
if(host_info.speed) if(host_info.speed)
opt |= SPEED_DUEL; opt |= SPEED_DUEL;
new_replay.WriteInt32((mainGame->GetMasterRule(opt, 0)) | (opt & SPEED_DUEL) << 8);
last_replay.WriteInt32(host_info.start_lp, false); last_replay.WriteInt32(host_info.start_lp, false);
last_replay.WriteInt32(host_info.start_hand, false); last_replay.WriteInt32(host_info.start_hand, false);
last_replay.WriteInt32(host_info.draw_count, false); last_replay.WriteInt32(host_info.draw_count, false);
...@@ -518,8 +531,14 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -518,8 +531,14 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
else startbuf[1] = 0x11; else startbuf[1] = 0x11;
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::SendBufferToPlayer(*oit, STOC_GAME_MSG, startbuf, 18); NetServer::SendBufferToPlayer(*oit, STOC_GAME_MSG, startbuf, 18);
startbuf[1] = 0;
ReplayPacket p((char*)startbuf, 17);
replay_stream.push_back(p);
PseudoRefreshDeck(0);
PseudoRefreshDeck(1);
RefreshExtra(0); RefreshExtra(0);
RefreshExtra(1); RefreshExtra(1);
new_replay.WriteStream(replay_stream);
start_duel(pduel, opt); start_duel(pduel, opt);
Process(); Process();
} }
...@@ -594,6 +613,8 @@ void SingleDuel::Surrender(DuelPlayer* dp) { ...@@ -594,6 +613,8 @@ void SingleDuel::Surrender(DuelPlayer* dp) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
ReplayPacket p((char*)wbuf, 3);
replay_stream.push_back(p);
if(players[player] == pplayer[player]) { if(players[player] == pplayer[player]) {
match_result[duel_count++] = 1 - player; match_result[duel_count++] = 1 - player;
tp_player = player; tp_player = player;
...@@ -609,12 +630,19 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -609,12 +630,19 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) {
char* offset, *pbufw, *pbuf = msgbuffer; char* offset, *pbufw, *pbuf = msgbuffer;
int player, count, type; int player, count, type;
while (pbuf - msgbuffer < (int)len) { while (pbuf - msgbuffer < (int)len) {
replay_stream.clear();
bool record = true;
ReplayPacket p;
offset = pbuf; offset = pbuf;
unsigned char engType = BufferIO::ReadUInt8(pbuf); unsigned char engType = BufferIO::ReadUInt8(pbuf);
p.message = engType;
p.length = len - 1;
memcpy(p.data, pbuf, p.length);
switch (engType) { switch (engType) {
case MSG_RETRY: { case MSG_RETRY: {
WaitforResponse(last_response); WaitforResponse(last_response);
NetServer::SendBufferToPlayer(players[last_response], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[last_response], STOC_GAME_MSG, offset, pbuf - offset);
replay_stream.push_back(p);
return 1; return 1;
} }
case MSG_HINT: { case MSG_HINT: {
...@@ -627,6 +655,7 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -627,6 +655,7 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) {
case 3: case 3:
case 5: { case 5: {
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, offset, pbuf - offset);
record = false;
break; break;
} }
case 4: case 4:
...@@ -666,6 +695,7 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -666,6 +695,7 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) {
match_result[duel_count++] = 1 - player; match_result[duel_count++] = 1 - player;
tp_player = player; tp_player = player;
} }
replay_stream.push_back(p);
EndDuel(); EndDuel();
return 2; return 2;
} }
...@@ -872,6 +902,7 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -872,6 +902,7 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
PseudoRefreshDeck(player);
break; break;
} }
case MSG_SHUFFLE_HAND: { case MSG_SHUFFLE_HAND: {
...@@ -920,6 +951,8 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -920,6 +951,8 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
PseudoRefreshDeck(0);
PseudoRefreshDeck(1);
break; break;
} }
case MSG_DECK_TOP: { case MSG_DECK_TOP: {
...@@ -1432,6 +1465,12 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -1432,6 +1465,12 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) {
break; break;
} }
} }
//setting the length again in case of multiple messages in a row,
//when the packet will be written in the replay, the extra data registered previously will be discarded
p.length = (pbuf - offset) - 1;
if (record)
replay_stream.insert(replay_stream.begin(), p);
new_replay.WriteStream(replay_stream);
} }
return 0; return 0;
} }
...@@ -1453,11 +1492,28 @@ void SingleDuel::GetResponse(DuelPlayer* dp, void* pdata, unsigned int len) { ...@@ -1453,11 +1492,28 @@ void SingleDuel::GetResponse(DuelPlayer* dp, void* pdata, unsigned int len) {
void SingleDuel::EndDuel() { void SingleDuel::EndDuel() {
if(!pduel) if(!pduel)
return; return;
last_replay.EndRecord(); last_replay.EndRecord(0x1000);
char replaybuf[0x2000], *pbuf = replaybuf; char replaybuf[0x2000], *pbuf = replaybuf;
memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader)); memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader));
pbuf += sizeof(ReplayHeader); pbuf += sizeof(ReplayHeader);
memcpy(pbuf, last_replay.comp_data, last_replay.comp_size); memcpy(pbuf, last_replay.comp_data, last_replay.comp_size);
replay_stream.push_back(ReplayPacket(OLD_REPLAY_MODE, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size));
//in case of remaining packets, e.g. MSG_WIN
new_replay.WriteStream(replay_stream);
new_replay.EndRecord();
char nreplaybuf[0x2000], *npbuf = nreplaybuf;
memcpy(npbuf, &new_replay.pheader, sizeof(ReplayHeader));
npbuf += sizeof(ReplayHeader);
memcpy(npbuf, new_replay.comp_data, new_replay.comp_size);
NetServer::SendBufferToPlayer(players[0], STOC_NEW_REPLAY, nreplaybuf, sizeof(ReplayHeader) + new_replay.comp_size);
NetServer::ReSendToPlayer(players[1]);
for (auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size); NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
...@@ -1497,8 +1553,10 @@ void SingleDuel::RefreshMzone(int player, int flag, int use_cache) { ...@@ -1497,8 +1553,10 @@ void SingleDuel::RefreshMzone(int player, int flag, int use_cache) {
BufferIO::WriteInt8(qbuf, LOCATION_MZONE); BufferIO::WriteInt8(qbuf, LOCATION_MZONE);
int len = query_field_card(pduel, player, LOCATION_MZONE, flag, (unsigned char*)qbuf, use_cache); int len = query_field_card(pduel, player, LOCATION_MZONE, flag, (unsigned char*)qbuf, use_cache);
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer, len + 3); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
int qlen = 0; int qlen = 0;
while(qlen < len) { while (qlen < len) {
int clen = BufferIO::ReadInt32(qbuf); int clen = BufferIO::ReadInt32(qbuf);
qlen += clen; qlen += clen;
if (clen == 4) if (clen == 4)
...@@ -1519,8 +1577,10 @@ void SingleDuel::RefreshSzone(int player, int flag, int use_cache) { ...@@ -1519,8 +1577,10 @@ void SingleDuel::RefreshSzone(int player, int flag, int use_cache) {
BufferIO::WriteInt8(qbuf, LOCATION_SZONE); BufferIO::WriteInt8(qbuf, LOCATION_SZONE);
int len = query_field_card(pduel, player, LOCATION_SZONE, flag, (unsigned char*)qbuf, use_cache); int len = query_field_card(pduel, player, LOCATION_SZONE, flag, (unsigned char*)qbuf, use_cache);
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer, len + 3); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
int qlen = 0; int qlen = 0;
while(qlen < len) { while (qlen < len) {
int clen = BufferIO::ReadInt32(qbuf); int clen = BufferIO::ReadInt32(qbuf);
qlen += clen; qlen += clen;
if (clen == 4) if (clen == 4)
...@@ -1558,6 +1618,8 @@ void SingleDuel::RefreshHand(int player, int flag, int use_cache) { ...@@ -1558,6 +1618,8 @@ void SingleDuel::RefreshHand(int player, int flag, int use_cache) {
NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer, len + 3); NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer, len + 3);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
} }
void SingleDuel::RefreshGrave(int player, int flag, int use_cache) { void SingleDuel::RefreshGrave(int player, int flag, int use_cache) {
char query_buffer[0x2000]; char query_buffer[0x2000];
...@@ -1570,6 +1632,8 @@ void SingleDuel::RefreshGrave(int player, int flag, int use_cache) { ...@@ -1570,6 +1632,8 @@ void SingleDuel::RefreshGrave(int player, int flag, int use_cache) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
} }
void SingleDuel::RefreshExtra(int player, int flag, int use_cache) { void SingleDuel::RefreshExtra(int player, int flag, int use_cache) {
char query_buffer[0x2000]; char query_buffer[0x2000];
...@@ -1579,6 +1643,8 @@ void SingleDuel::RefreshExtra(int player, int flag, int use_cache) { ...@@ -1579,6 +1643,8 @@ void SingleDuel::RefreshExtra(int player, int flag, int use_cache) {
BufferIO::WriteInt8(qbuf, LOCATION_EXTRA); BufferIO::WriteInt8(qbuf, LOCATION_EXTRA);
int len = query_field_card(pduel, player, LOCATION_EXTRA, flag, (unsigned char*)qbuf, use_cache); int len = query_field_card(pduel, player, LOCATION_EXTRA, flag, (unsigned char*)qbuf, use_cache);
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer, len + 3); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
} }
void SingleDuel::RefreshSingle(int player, int location, int sequence, int flag) { void SingleDuel::RefreshSingle(int player, int location, int sequence, int flag) {
char query_buffer[0x2000]; char query_buffer[0x2000];
...@@ -1589,6 +1655,8 @@ void SingleDuel::RefreshSingle(int player, int location, int sequence, int flag) ...@@ -1589,6 +1655,8 @@ void SingleDuel::RefreshSingle(int player, int location, int sequence, int flag)
BufferIO::WriteInt8(qbuf, sequence); BufferIO::WriteInt8(qbuf, sequence);
int len = query_card(pduel, player, location, sequence, flag, (unsigned char*)qbuf, 0); int len = query_card(pduel, player, location, sequence, flag, (unsigned char*)qbuf, 0);
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer, len + 4); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer, len + 4);
ReplayPacket p((char*)query_buffer, len + 3);
replay_stream.push_back(p);
if(location == LOCATION_REMOVED && (qbuf[15] & POS_FACEDOWN)) if(location == LOCATION_REMOVED && (qbuf[15] & POS_FACEDOWN))
return; return;
if ((location & 0x90) || ((location & 0x2c) && (qbuf[15] & POS_FACEUP))) { if ((location & 0x90) || ((location & 0x2c) && (qbuf[15] & POS_FACEUP))) {
...@@ -1597,6 +1665,16 @@ void SingleDuel::RefreshSingle(int player, int location, int sequence, int flag) ...@@ -1597,6 +1665,16 @@ void SingleDuel::RefreshSingle(int player, int location, int sequence, int flag)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
} }
} }
void SingleDuel::PseudoRefreshDeck(int player, int flag) {
char query_buffer[0x2000];
char* qbuf = query_buffer;
BufferIO::WriteInt8(qbuf, MSG_UPDATE_DATA);
BufferIO::WriteInt8(qbuf, player);
BufferIO::WriteInt8(qbuf, LOCATION_DECK);
int len = query_field_card(pduel, player, LOCATION_DECK, flag, (unsigned char*)qbuf, 0);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
}
int SingleDuel::MessageHandler(long fduel, int type) { int SingleDuel::MessageHandler(long fduel, int type) {
if(!enable_log) if(!enable_log)
return 0; return 0;
...@@ -1618,6 +1696,8 @@ void SingleDuel::SingleTimer(evutil_socket_t fd, short events, void* arg) { ...@@ -1618,6 +1696,8 @@ void SingleDuel::SingleTimer(evutil_socket_t fd, short events, void* arg) {
NetServer::ReSendToPlayer(sd->players[1]); NetServer::ReSendToPlayer(sd->players[1]);
for(auto oit = sd->observers.begin(); oit != sd->observers.end(); ++oit) for(auto oit = sd->observers.begin(); oit != sd->observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
ReplayPacket p((char*)wbuf, 3);
sd->replay_stream.push_back(p);
if(sd->players[player] == sd->pplayer[player]) { if(sd->players[player] == sd->pplayer[player]) {
sd->match_result[sd->duel_count++] = 1 - player; sd->match_result[sd->duel_count++] = 1 - player;
sd->tp_player = player; sd->tp_player = player;
......
...@@ -41,6 +41,9 @@ public: ...@@ -41,6 +41,9 @@ public:
static int MessageHandler(long fduel, int type); static int MessageHandler(long fduel, int type);
static void SingleTimer(evutil_socket_t fd, short events, void* arg); static void SingleTimer(evutil_socket_t fd, short events, void* arg);
void PseudoRefreshDeck(int player, int flag = 0x181fff);
static std::vector<ReplayPacket> replay_stream;
protected: protected:
DuelPlayer* players[2]; DuelPlayer* players[2];
DuelPlayer* pplayer[2]; DuelPlayer* pplayer[2];
...@@ -51,6 +54,7 @@ protected: ...@@ -51,6 +54,7 @@ protected:
unsigned char last_response; unsigned char last_response;
std::set<DuelPlayer*> observers; std::set<DuelPlayer*> observers;
Replay last_replay; Replay last_replay;
Replay new_replay;
bool match_mode; bool match_mode;
int match_kill; int match_kill;
bool game_started; bool game_started;
......
...@@ -11,6 +11,8 @@ long SingleMode::pduel = 0; ...@@ -11,6 +11,8 @@ long SingleMode::pduel = 0;
bool SingleMode::is_closing = false; bool SingleMode::is_closing = false;
bool SingleMode::is_continuing = false; bool SingleMode::is_continuing = false;
Replay SingleMode::last_replay; Replay SingleMode::last_replay;
Replay SingleMode::new_replay;
std::vector<ReplayPacket> SingleMode::replay_stream;
static byte buffer[0x20000]; static byte buffer[0x20000];
...@@ -106,16 +108,21 @@ int SingleMode::SinglePlayThread(void* param) { ...@@ -106,16 +108,21 @@ int SingleMode::SinglePlayThread(void* param) {
char engineBuffer[0x1000]; char engineBuffer[0x1000];
is_closing = false; is_closing = false;
is_continuing = true; is_continuing = true;
int len = get_message(pduel, (byte*)engineBuffer); last_replay.BeginRecord(false);
if (len > 0)
is_continuing = SinglePlayAnalyze(engineBuffer, len);
last_replay.BeginRecord();
last_replay.WriteHeader(rh); last_replay.WriteHeader(rh);
//records the replay with the new system
new_replay.BeginRecord();
rh.id = 0x58707279;
rh.flag |= REPLAY_NEWREPLAY;
new_replay.WriteHeader(rh);
replay_stream.clear();
unsigned short buffer[20]; unsigned short buffer[20];
BufferIO::CopyWStr(mainGame->dInfo.hostname, buffer, 20); BufferIO::CopyWStr(mainGame->dInfo.hostname, buffer, 20);
last_replay.WriteData(buffer, 40, false); last_replay.WriteData(buffer, 40, false);
new_replay.WriteData(buffer, 40, false);
BufferIO::CopyWStr(mainGame->dInfo.clientname, buffer, 20); BufferIO::CopyWStr(mainGame->dInfo.clientname, buffer, 20);
last_replay.WriteData(buffer, 40, false); last_replay.WriteData(buffer, 40, false);
new_replay.WriteData(buffer, 40, false);
last_replay.WriteInt32(start_lp, false); last_replay.WriteInt32(start_lp, false);
last_replay.WriteInt32(start_hand, false); last_replay.WriteInt32(start_hand, false);
last_replay.WriteInt32(draw_count, false); last_replay.WriteInt32(draw_count, false);
...@@ -123,6 +130,11 @@ int SingleMode::SinglePlayThread(void* param) { ...@@ -123,6 +130,11 @@ int SingleMode::SinglePlayThread(void* param) {
last_replay.WriteInt16(slen, false); last_replay.WriteInt16(slen, false);
last_replay.WriteData(filename, slen, false); last_replay.WriteData(filename, slen, false);
last_replay.Flush(); last_replay.Flush();
new_replay.WriteInt32((mainGame->GetMasterRule(opt, 0)) | (opt & SPEED_DUEL) << 8);
int len = get_message(pduel, (byte*)engineBuffer);
if (len > 0){
is_continuing = SinglePlayAnalyze(engineBuffer, len);
}
start_duel(pduel, opt); start_duel(pduel, opt);
while (is_continuing) { while (is_continuing) {
int result = process(pduel); int result = process(pduel);
...@@ -133,7 +145,15 @@ int SingleMode::SinglePlayThread(void* param) { ...@@ -133,7 +145,15 @@ int SingleMode::SinglePlayThread(void* param) {
is_continuing = SinglePlayAnalyze(engineBuffer, len); is_continuing = SinglePlayAnalyze(engineBuffer, len);
} }
} }
last_replay.EndRecord(); last_replay.EndRecord(0x1000);
char replaybuf[0x2000], *pbuf = replaybuf;
memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader));
pbuf += sizeof(ReplayHeader);
memcpy(pbuf, last_replay.comp_data, last_replay.comp_size);
new_replay.WritePacket(ReplayPacket(OLD_REPLAY_MODE, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size));
new_replay.EndRecord();
time_t nowtime = time(NULL); time_t nowtime = time(NULL);
struct tm *localedtime = localtime(&nowtime); struct tm *localedtime = localtime(&nowtime);
char timebuf[40]; char timebuf[40];
...@@ -146,8 +166,8 @@ int SingleMode::SinglePlayThread(void* param) { ...@@ -146,8 +166,8 @@ int SingleMode::SinglePlayThread(void* param) {
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
mainGame->replaySignal.Reset(); mainGame->replaySignal.Reset();
mainGame->replaySignal.Wait(); mainGame->replaySignal.Wait();
if(mainGame->actionParam) if(mainGame->saveReplay)
last_replay.SaveReplay(mainGame->ebRSName->getText()); new_replay.SaveReplay(mainGame->ebRSName->getText());
end_duel(pduel); end_duel(pduel);
if(!is_closing) { if(!is_closing) {
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
...@@ -171,10 +191,16 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -171,10 +191,16 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
char* offset, *pbuf = msg; char* offset, *pbuf = msg;
int player, count; int player, count;
while (pbuf - msg < (int)len) { while (pbuf - msg < (int)len) {
replay_stream.clear();
bool record = true;
if(is_closing || !is_continuing) if(is_closing || !is_continuing)
return false; return false;
offset = pbuf; offset = pbuf;
ReplayPacket p;
mainGame->dInfo.curMsg = BufferIO::ReadUInt8(pbuf); mainGame->dInfo.curMsg = BufferIO::ReadUInt8(pbuf);
p.message = mainGame->dInfo.curMsg;
p.length = len - 1;
memcpy(p.data, pbuf, p.length);
switch (mainGame->dInfo.curMsg) { switch (mainGame->dInfo.curMsg) {
case MSG_RETRY: { case MSG_RETRY: {
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
...@@ -186,16 +212,19 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -186,16 +212,19 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
return false; return false;
} }
case MSG_HINT: { case MSG_HINT: {
/*int type = */BufferIO::ReadInt8(pbuf); int type = BufferIO::ReadInt8(pbuf);
int player = BufferIO::ReadInt8(pbuf); int player = BufferIO::ReadInt8(pbuf);
/*int data = */BufferIO::ReadInt64(pbuf); /*int data = */BufferIO::ReadInt64(pbuf);
if(player == 0) if(player == 0)
DuelClient::ClientAnalyze(offset, pbuf - offset); DuelClient::ClientAnalyze(offset, pbuf - offset);
if (type > 0 && type < 6 && type != 4)
record = false;
break; break;
} }
case MSG_WIN: { case MSG_WIN: {
pbuf += 2; pbuf += 2;
DuelClient::ClientAnalyze(offset, pbuf - offset); DuelClient::ClientAnalyze(offset, pbuf - offset);
replay_stream.push_back(p);
return false; return false;
} }
case MSG_SELECT_BATTLECMD: { case MSG_SELECT_BATTLECMD: {
...@@ -209,6 +238,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -209,6 +238,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SELECT_IDLECMD: { case MSG_SELECT_IDLECMD: {
...@@ -230,6 +260,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -230,6 +260,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SELECT_EFFECTYN: { case MSG_SELECT_EFFECTYN: {
...@@ -240,6 +271,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -240,6 +271,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SELECT_YESNO: { case MSG_SELECT_YESNO: {
...@@ -249,6 +281,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -249,6 +281,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SELECT_OPTION: { case MSG_SELECT_OPTION: {
...@@ -259,6 +292,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -259,6 +292,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SELECT_CARD: case MSG_SELECT_CARD:
...@@ -271,6 +305,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -271,6 +305,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SELECT_UNSELECT_CARD: { case MSG_SELECT_UNSELECT_CARD: {
...@@ -284,6 +319,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -284,6 +319,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SELECT_CHAIN: { case MSG_SELECT_CHAIN: {
...@@ -294,6 +330,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -294,6 +330,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SELECT_PLACE: case MSG_SELECT_PLACE:
...@@ -304,6 +341,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -304,6 +341,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SELECT_POSITION: { case MSG_SELECT_POSITION: {
...@@ -313,6 +351,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -313,6 +351,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SELECT_COUNTER: { case MSG_SELECT_COUNTER: {
...@@ -324,6 +363,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -324,6 +363,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SELECT_SUM: { case MSG_SELECT_SUM: {
...@@ -338,6 +378,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -338,6 +378,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_SORT_CARD: case MSG_SORT_CARD:
...@@ -349,6 +390,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -349,6 +390,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_CONFIRM_DECKTOP: { case MSG_CONFIRM_DECKTOP: {
...@@ -375,7 +417,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -375,7 +417,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
case MSG_SHUFFLE_DECK: { case MSG_SHUFFLE_DECK: {
player = BufferIO::ReadInt8(pbuf); player = BufferIO::ReadInt8(pbuf);
DuelClient::ClientAnalyze(offset, pbuf - offset); DuelClient::ClientAnalyze(offset, pbuf - offset);
SinglePlayRefreshDeck(player); SinglePlayRefresh(player, LOCATION_DECK, 0x181fff);
break; break;
} }
case MSG_SHUFFLE_HAND: { case MSG_SHUFFLE_HAND: {
...@@ -400,13 +442,13 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -400,13 +442,13 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
case MSG_SWAP_GRAVE_DECK: { case MSG_SWAP_GRAVE_DECK: {
player = BufferIO::ReadInt8(pbuf); player = BufferIO::ReadInt8(pbuf);
DuelClient::ClientAnalyze(offset, pbuf - offset); DuelClient::ClientAnalyze(offset, pbuf - offset);
SinglePlayRefreshGrave(player); SinglePlayRefresh(player, LOCATION_GRAVE, 0x181fff);
break; break;
} }
case MSG_REVERSE_DECK: { case MSG_REVERSE_DECK: {
DuelClient::ClientAnalyze(offset, pbuf - offset); DuelClient::ClientAnalyze(offset, pbuf - offset);
SinglePlayRefreshDeck(0); SinglePlayRefresh(0, LOCATION_DECK, 0x181fff);
SinglePlayRefreshDeck(1); SinglePlayRefresh(1, LOCATION_DECK, 0x181fff);
break; break;
} }
case MSG_DECK_TOP: { case MSG_DECK_TOP: {
...@@ -521,8 +563,8 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -521,8 +563,8 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
case MSG_CHAIN_END: { case MSG_CHAIN_END: {
DuelClient::ClientAnalyze(offset, pbuf - offset); DuelClient::ClientAnalyze(offset, pbuf - offset);
SinglePlayRefresh(); SinglePlayRefresh();
SinglePlayRefreshDeck(0); SinglePlayRefresh(0, LOCATION_DECK, 0x181fff);
SinglePlayRefreshDeck(1); SinglePlayRefresh(1, LOCATION_DECK, 0x181fff);
break; break;
} }
case MSG_CHAIN_NEGATED: { case MSG_CHAIN_NEGATED: {
...@@ -655,6 +697,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -655,6 +697,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_HAND_RES: { case MSG_HAND_RES: {
...@@ -669,6 +712,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -669,6 +712,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_ANNOUNCE_ATTRIB: { case MSG_ANNOUNCE_ATTRIB: {
...@@ -678,6 +722,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -678,6 +722,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_ANNOUNCE_CARD: { case MSG_ANNOUNCE_CARD: {
...@@ -687,6 +732,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -687,6 +732,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_ANNOUNCE_NUMBER: case MSG_ANNOUNCE_NUMBER:
...@@ -698,6 +744,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -698,6 +744,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
mainGame->singleSignal.Reset(); mainGame->singleSignal.Reset();
mainGame->singleSignal.Wait(); mainGame->singleSignal.Wait();
} }
record = false;
break; break;
} }
case MSG_CARD_HINT: { case MSG_CARD_HINT: {
...@@ -714,8 +761,8 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -714,8 +761,8 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
player = pbuf[0]; player = pbuf[0];
pbuf += pbuf[2] * 4 + pbuf[4] * 4 + 9; pbuf += pbuf[2] * 4 + pbuf[4] * 4 + 9;
DuelClient::ClientAnalyze(offset, pbuf - offset); DuelClient::ClientAnalyze(offset, pbuf - offset);
SinglePlayRefreshDeck(player); SinglePlayRefresh(player, LOCATION_DECK, 0x181fff);
SinglePlayRefreshExtra(player); SinglePlayRefresh(player, LOCATION_EXTRA, 0x181fff);
break; break;
} }
case MSG_MATCH_KILL: { case MSG_MATCH_KILL: {
...@@ -728,43 +775,6 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -728,43 +775,6 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
int rule = BufferIO::ReadInt8(pbuf); int rule = BufferIO::ReadInt8(pbuf);
mainGame->dInfo.duel_field = rule & 0xf; mainGame->dInfo.duel_field = rule & 0xf;
mainGame->dInfo.extraval = rule >> 4; mainGame->dInfo.extraval = rule >> 4;
// reset master rule 4 phase button position
mainGame->wPhase->setRelativePosition(mainGame->Resize(480, 310, 855, 330));
if(mainGame->dInfo.extraval) {
if(mainGame->dInfo.duel_field >= 4) {
mainGame->wPhase->setRelativePosition(mainGame->Resize(480, 290, 855, 350));
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnDP->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnSP->setRelativePosition(mainGame->Resize(0, 40, 50, 60));
mainGame->btnM1->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnBP->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnM2->setRelativePosition(mainGame->Resize(160, 20, 210, 40));
mainGame->btnEP->setRelativePosition(mainGame->Resize(310, 0, 360, 20));
} else {
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnDP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnSP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(130, 0, 180, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(195, 0, 245, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
mainGame->btnEP->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
}
} else {
mainGame->btnDP->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
if(mainGame->dInfo.duel_field >= 4) {
mainGame->btnSP->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(160, 0, 210, 20));
} else {
mainGame->btnSP->setRelativePosition(mainGame->Resize(65, 0, 115, 20));
mainGame->btnM1->setRelativePosition(mainGame->Resize(130, 0, 180, 20));
mainGame->btnBP->setRelativePosition(mainGame->Resize(195, 0, 245, 20));
mainGame->btnM2->setRelativePosition(mainGame->Resize(260, 0, 310, 20));
}
mainGame->btnEP->setRelativePosition(mainGame->Resize(320, 0, 370, 20));
mainGame->btnShuffle->setRelativePosition(mainGame->Resize(0, 0, 50, 20));
}
int val = 0; int val = 0;
for(int p = 0; p < 2; ++p) { for(int p = 0; p < 2; ++p) {
mainGame->dInfo.lp[p] = BufferIO::ReadInt32(pbuf); mainGame->dInfo.lp[p] = BufferIO::ReadInt32(pbuf);
...@@ -858,80 +868,64 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) { ...@@ -858,80 +868,64 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
break; break;
} }
} }
//setting the length again in case of multiple messages in a row,
//when the packet will be written in the replay, the extra data registered previously will be discarded
p.length = (pbuf - offset) - 1;
if (record)
replay_stream.insert(replay_stream.begin(), p);
new_replay.WriteStream(replay_stream);
} }
return is_continuing; return is_continuing;
} }
void SingleMode::SinglePlayRefresh(int flag) { void SingleMode::SinglePlayRefresh(int player, int location, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, 0, LOCATION_MZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_MZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_MZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_MZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_SZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_SZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_SZONE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_SZONE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_HAND, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_HAND, (char*)queryBuffer);
}
void SingleMode::SinglePlayRefreshHand(int player, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_HAND, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_HAND, (char*)queryBuffer);
}
void SingleMode::SinglePlayRefreshGrave(int player, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_GRAVE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_GRAVE, (char*)queryBuffer);
}
void SingleMode::SinglePlayRefreshDeck(int player, int flag) {
unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_DECK, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_DECK, (char*)queryBuffer);
}
void SingleMode::SinglePlayRefreshExtra(int player, int flag) {
unsigned char queryBuffer[0x2000]; unsigned char queryBuffer[0x2000];
/*int len = */query_field_card(pduel, player, LOCATION_EXTRA, flag, queryBuffer, 0); char queryBuffer2[0x2000];
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), LOCATION_EXTRA, (char*)queryBuffer); char* qbuf = queryBuffer2;
ReplayPacket p;
int len = query_field_card(pduel, player, location, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(player), location, (char*)queryBuffer);
BufferIO::WriteInt8(qbuf, player);
BufferIO::WriteInt8(qbuf, location);
memcpy(qbuf, (char*)queryBuffer, len);
replay_stream.push_back(ReplayPacket(MSG_UPDATE_DATA, queryBuffer2, len + 2));
} }
void SingleMode::SinglePlayRefreshSingle(int player, int location, int sequence, int flag) { void SingleMode::SinglePlayRefreshSingle(int player, int location, int sequence, int flag) {
unsigned char queryBuffer[0x2000]; unsigned char queryBuffer[0x2000];
/*int len = */query_card(pduel, player, location, sequence, flag, queryBuffer, 0); char queryBuffer2[0x2000];
char* qbuf = queryBuffer2;
int len = query_card(pduel, player, location, sequence, flag, queryBuffer, 0);
mainGame->dField.UpdateCard(mainGame->LocalPlayer(player), location, sequence, (char*)queryBuffer); mainGame->dField.UpdateCard(mainGame->LocalPlayer(player), location, sequence, (char*)queryBuffer);
BufferIO::WriteInt8(qbuf, player);
BufferIO::WriteInt8(qbuf, location);
BufferIO::WriteInt8(qbuf, sequence);
memcpy(qbuf, (char*)queryBuffer, len);
ReplayPacket p(MSG_UPDATE_CARD, queryBuffer2, len + 3);
replay_stream.push_back(p);
}
void SingleMode::SinglePlayRefresh(int flag) {
SinglePlayRefresh(0, LOCATION_MZONE, flag);
SinglePlayRefresh(1, LOCATION_MZONE, flag);
SinglePlayRefresh(0, LOCATION_SZONE, flag);
SinglePlayRefresh(1, LOCATION_SZONE, flag);
SinglePlayRefresh(0, LOCATION_HAND, flag);
SinglePlayRefresh(1, LOCATION_HAND, flag);
} }
void SingleMode::SinglePlayReload() { void SingleMode::SinglePlayReload() {
unsigned char queryBuffer[0x2000];
unsigned int flag = 0xffdfff; unsigned int flag = 0xffdfff;
/*int len = */query_field_card(pduel, 0, LOCATION_MZONE, flag, queryBuffer, 0); SinglePlayRefresh(0, LOCATION_MZONE, flag);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_MZONE, (char*)queryBuffer); SinglePlayRefresh(1, LOCATION_MZONE, flag);
/*len = */query_field_card(pduel, 1, LOCATION_MZONE, flag, queryBuffer, 0); SinglePlayRefresh(0, LOCATION_SZONE, flag);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_MZONE, (char*)queryBuffer); SinglePlayRefresh(1, LOCATION_SZONE, flag);
/*len = */query_field_card(pduel, 0, LOCATION_SZONE, flag, queryBuffer, 0); SinglePlayRefresh(0, LOCATION_HAND, flag);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_SZONE, (char*)queryBuffer); SinglePlayRefresh(1, LOCATION_HAND, flag);
/*len = */query_field_card(pduel, 1, LOCATION_SZONE, flag, queryBuffer, 0); SinglePlayRefresh(0, LOCATION_DECK, flag);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_SZONE, (char*)queryBuffer); SinglePlayRefresh(1, LOCATION_DECK, flag);
/*len = */query_field_card(pduel, 0, LOCATION_HAND, flag, queryBuffer, 0); SinglePlayRefresh(0, LOCATION_EXTRA, flag);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_HAND, (char*)queryBuffer); SinglePlayRefresh(1, LOCATION_EXTRA, flag);
/*len = */query_field_card(pduel, 1, LOCATION_HAND, flag, queryBuffer, 0); SinglePlayRefresh(0, LOCATION_GRAVE, flag);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_HAND, (char*)queryBuffer); SinglePlayRefresh(1, LOCATION_GRAVE, flag);
/*len = */query_field_card(pduel, 0, LOCATION_DECK, flag, queryBuffer, 0); SinglePlayRefresh(0, LOCATION_REMOVED, flag);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_DECK, (char*)queryBuffer); SinglePlayRefresh(1, LOCATION_REMOVED, flag);
/*len = */query_field_card(pduel, 1, LOCATION_DECK, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_DECK, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_EXTRA, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_EXTRA, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_EXTRA, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_EXTRA, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_GRAVE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_GRAVE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_GRAVE, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_GRAVE, (char*)queryBuffer);
/*len = */query_field_card(pduel, 0, LOCATION_REMOVED, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(0), LOCATION_REMOVED, (char*)queryBuffer);
/*len = */query_field_card(pduel, 1, LOCATION_REMOVED, flag, queryBuffer, 0);
mainGame->dField.UpdateFieldCard(mainGame->LocalPlayer(1), LOCATION_REMOVED, (char*)queryBuffer);
} }
byte* SingleMode::ScriptReader(const char* script_name, int* slen) { byte* SingleMode::ScriptReader(const char* script_name, int* slen) {
FILE *fp; FILE *fp;
......
...@@ -18,11 +18,8 @@ public: ...@@ -18,11 +18,8 @@ public:
static int SinglePlayThread(void* param); static int SinglePlayThread(void* param);
static bool SinglePlayAnalyze(char* msg, unsigned int len); static bool SinglePlayAnalyze(char* msg, unsigned int len);
static void SinglePlayRefresh(int player, int location, int flag = 0xf81fff);
static void SinglePlayRefresh(int flag = 0xf81fff); static void SinglePlayRefresh(int flag = 0xf81fff);
static void SinglePlayRefreshHand(int player, int flag = 0x781fff);
static void SinglePlayRefreshGrave(int player, int flag = 0x181fff);
static void SinglePlayRefreshDeck(int player, int flag = 0x181fff);
static void SinglePlayRefreshExtra(int player, int flag = 0x181fff);
static void SinglePlayRefreshSingle(int player, int location, int sequence, int flag = 0xf81fff); static void SinglePlayRefreshSingle(int player, int location, int sequence, int flag = 0xf81fff);
static void SinglePlayReload(); static void SinglePlayReload();
...@@ -31,6 +28,8 @@ public: ...@@ -31,6 +28,8 @@ public:
protected: protected:
static Replay last_replay; static Replay last_replay;
static Replay new_replay;
static std::vector<ReplayPacket> replay_stream;
}; };
} }
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
namespace ygo { namespace ygo {
std::vector<ReplayPacket> TagDuel::replay_stream;
TagDuel::TagDuel() { TagDuel::TagDuel() {
game_started = false; game_started = false;
for(int i = 0; i < 4; ++i) { for(int i = 0; i < 4; ++i) {
...@@ -355,13 +357,23 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -355,13 +357,23 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
rh.flag = REPLAY_TAG + REPLAY_LUA64; rh.flag = REPLAY_TAG + REPLAY_LUA64;
time_t seed = time(0); time_t seed = time(0);
rh.seed = seed; rh.seed = seed;
last_replay.BeginRecord(); last_replay.BeginRecord(false);
last_replay.WriteHeader(rh); last_replay.WriteHeader(rh);
rnd.reset(seed); rnd.reset(seed);
last_replay.WriteData(players[0]->name, 40, false); last_replay.WriteData(players[0]->name, 40, false);
last_replay.WriteData(players[1]->name, 40, false); last_replay.WriteData(players[1]->name, 40, false);
last_replay.WriteData(players[2]->name, 40, false); last_replay.WriteData(players[2]->name, 40, false);
last_replay.WriteData(players[3]->name, 40, false); last_replay.WriteData(players[3]->name, 40, false);
//records the replay with the new system
new_replay.BeginRecord();
rh.id = 0x58707279;
rh.flag |= REPLAY_NEWREPLAY;
new_replay.WriteHeader(rh);
new_replay.WriteData(players[0]->name, 40, false);
new_replay.WriteData(players[1]->name, 40, false);
new_replay.WriteData(players[2]->name, 40, false);
new_replay.WriteData(players[3]->name, 40);
replay_stream.clear();
if(!host_info.no_shuffle_deck) { if(!host_info.no_shuffle_deck) {
for(size_t i = pdeck[0].main.size() - 1; i > 0; --i) { for(size_t i = pdeck[0].main.size() - 1; i > 0; --i) {
int swap = rnd.real() * (i + 1); int swap = rnd.real() * (i + 1);
...@@ -395,6 +407,7 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -395,6 +407,7 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
if(host_info.speed) if(host_info.speed)
opt |= SPEED_DUEL; opt |= SPEED_DUEL;
opt |= DUEL_TAG_MODE; opt |= DUEL_TAG_MODE;
new_replay.WriteInt32((mainGame->GetMasterRule(opt, 0)) | (opt & SPEED_DUEL) << 8);
last_replay.WriteInt32(host_info.start_lp, false); last_replay.WriteInt32(host_info.start_lp, false);
last_replay.WriteInt32(host_info.start_hand, false); last_replay.WriteInt32(host_info.start_hand, false);
last_replay.WriteInt32(host_info.draw_count, false); last_replay.WriteInt32(host_info.draw_count, false);
...@@ -519,8 +532,14 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -519,8 +532,14 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
else startbuf[1] = 0x11; else startbuf[1] = 0x11;
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::SendBufferToPlayer(*oit, STOC_GAME_MSG, startbuf, 18); NetServer::SendBufferToPlayer(*oit, STOC_GAME_MSG, startbuf, 18);
startbuf[1] = 0;
ReplayPacket p((char*)startbuf, 17);
replay_stream.push_back(p);
PseudoRefreshDeck(0);
PseudoRefreshDeck(1);
RefreshExtra(0); RefreshExtra(0);
RefreshExtra(1); RefreshExtra(1);
new_replay.WriteStream(replay_stream);
start_duel(pduel, opt); start_duel(pduel, opt);
Process(); Process();
} }
...@@ -558,12 +577,19 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -558,12 +577,19 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
char* offset, *pbufw, *pbuf = msgbuffer; char* offset, *pbufw, *pbuf = msgbuffer;
int player, count, type; int player, count, type;
while (pbuf - msgbuffer < (int)len) { while (pbuf - msgbuffer < (int)len) {
replay_stream.clear();
bool record = true;
ReplayPacket p;
offset = pbuf; offset = pbuf;
unsigned char engType = BufferIO::ReadUInt8(pbuf); unsigned char engType = BufferIO::ReadUInt8(pbuf);
p.message = engType;
p.length = len - 1;
memcpy(p.data, pbuf, p.length);
switch (engType) { switch (engType) {
case MSG_RETRY: { case MSG_RETRY: {
WaitforResponse(last_response); WaitforResponse(last_response);
NetServer::SendBufferToPlayer(cur_player[last_response], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(cur_player[last_response], STOC_GAME_MSG, offset, pbuf - offset);
replay_stream.push_back(p);
return 1; return 1;
} }
case MSG_HINT: { case MSG_HINT: {
...@@ -577,6 +603,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -577,6 +603,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
case 5: case 5:
case 10: { case 10: {
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
record = false;
break; break;
} }
case 4: case 4:
...@@ -603,6 +630,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -603,6 +630,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
replay_stream.push_back(p);
EndDuel(); EndDuel();
return 2; return 2;
} }
...@@ -817,6 +845,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -817,6 +845,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
PseudoRefreshDeck(player);
break; break;
} }
case MSG_SHUFFLE_HAND: { case MSG_SHUFFLE_HAND: {
...@@ -875,6 +904,8 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -875,6 +904,8 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
PseudoRefreshDeck(0);
PseudoRefreshDeck(1);
break; break;
} }
case MSG_DECK_TOP: { case MSG_DECK_TOP: {
...@@ -1499,6 +1530,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -1499,6 +1530,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[p], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[p], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
PseudoRefreshDeck(player);
RefreshExtra(player); RefreshExtra(player);
RefreshMzone(0, 0x81fff, 0); RefreshMzone(0, 0x81fff, 0);
RefreshMzone(1, 0x81fff, 0); RefreshMzone(1, 0x81fff, 0);
...@@ -1513,6 +1545,12 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) { ...@@ -1513,6 +1545,12 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
break; break;
} }
} }
//setting the length again in case of multiple messages in a row,
//when the packet will be written in the replay, the extra data registered previously will be discarded
p.length = (pbuf - offset) - 1;
if (record)
replay_stream.insert(replay_stream.begin(), p);
new_replay.WriteStream(replay_stream);
} }
return 0; return 0;
} }
...@@ -1535,11 +1573,29 @@ void TagDuel::GetResponse(DuelPlayer* dp, void* pdata, unsigned int len) { ...@@ -1535,11 +1573,29 @@ void TagDuel::GetResponse(DuelPlayer* dp, void* pdata, unsigned int len) {
void TagDuel::EndDuel() { void TagDuel::EndDuel() {
if(!pduel) if(!pduel)
return; return;
last_replay.EndRecord(); last_replay.EndRecord(0x1000);
char replaybuf[0x2000], *pbuf = replaybuf; char replaybuf[0x2000], *pbuf = replaybuf;
memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader)); memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader));
pbuf += sizeof(ReplayHeader); pbuf += sizeof(ReplayHeader);
memcpy(pbuf, last_replay.comp_data, last_replay.comp_size); memcpy(pbuf, last_replay.comp_data, last_replay.comp_size);
replay_stream.push_back(ReplayPacket(OLD_REPLAY_MODE, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size));
//in case of remaining packets, e.g. MSG_WIN
new_replay.WriteStream(replay_stream);
new_replay.EndRecord();
char nreplaybuf[0x2000], *npbuf = nreplaybuf;
memcpy(npbuf, &new_replay.pheader, sizeof(ReplayHeader));
npbuf += sizeof(ReplayHeader);
memcpy(npbuf, new_replay.comp_data, new_replay.comp_size);
NetServer::SendBufferToPlayer(players[0], STOC_NEW_REPLAY, nreplaybuf, sizeof(ReplayHeader) + new_replay.comp_size);
NetServer::ReSendToPlayer(players[1]);
NetServer::ReSendToPlayer(players[2]);
NetServer::ReSendToPlayer(players[3]);
for (auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size); NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
NetServer::ReSendToPlayer(players[2]); NetServer::ReSendToPlayer(players[2]);
...@@ -1586,6 +1642,8 @@ void TagDuel::RefreshMzone(int player, int flag, int use_cache) { ...@@ -1586,6 +1642,8 @@ void TagDuel::RefreshMzone(int player, int flag, int use_cache) {
int len = query_field_card(pduel, player, LOCATION_MZONE, flag, (unsigned char*)qbuf, use_cache); int len = query_field_card(pduel, player, LOCATION_MZONE, flag, (unsigned char*)qbuf, use_cache);
int pid = (player == 0) ? 0 : 2; int pid = (player == 0) ? 0 : 2;
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 3); NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
NetServer::ReSendToPlayer(players[pid + 1]); NetServer::ReSendToPlayer(players[pid + 1]);
int qlen = 0; int qlen = 0;
while(qlen < len) { while(qlen < len) {
...@@ -1612,6 +1670,8 @@ void TagDuel::RefreshSzone(int player, int flag, int use_cache) { ...@@ -1612,6 +1670,8 @@ void TagDuel::RefreshSzone(int player, int flag, int use_cache) {
int len = query_field_card(pduel, player, LOCATION_SZONE, flag, (unsigned char*)qbuf, use_cache); int len = query_field_card(pduel, player, LOCATION_SZONE, flag, (unsigned char*)qbuf, use_cache);
int pid = (player == 0) ? 0 : 2; int pid = (player == 0) ? 0 : 2;
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 3); NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
NetServer::ReSendToPlayer(players[pid + 1]); NetServer::ReSendToPlayer(players[pid + 1]);
int qlen = 0; int qlen = 0;
while(qlen < len) { while(qlen < len) {
...@@ -1637,6 +1697,8 @@ void TagDuel::RefreshHand(int player, int flag, int use_cache) { ...@@ -1637,6 +1697,8 @@ void TagDuel::RefreshHand(int player, int flag, int use_cache) {
BufferIO::WriteInt8(qbuf, LOCATION_HAND); BufferIO::WriteInt8(qbuf, LOCATION_HAND);
int len = query_field_card(pduel, player, LOCATION_HAND, flag | QUERY_IS_PUBLIC, (unsigned char*)qbuf, use_cache); int len = query_field_card(pduel, player, LOCATION_HAND, flag | QUERY_IS_PUBLIC, (unsigned char*)qbuf, use_cache);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, query_buffer, len + 3); NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
int qlen = 0; int qlen = 0;
while(qlen < len) { while(qlen < len) {
int slen = BufferIO::ReadInt32(qbuf); int slen = BufferIO::ReadInt32(qbuf);
...@@ -1670,6 +1732,8 @@ void TagDuel::RefreshGrave(int player, int flag, int use_cache) { ...@@ -1670,6 +1732,8 @@ void TagDuel::RefreshGrave(int player, int flag, int use_cache) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
} }
void TagDuel::RefreshExtra(int player, int flag, int use_cache) { void TagDuel::RefreshExtra(int player, int flag, int use_cache) {
char query_buffer[0x2000]; char query_buffer[0x2000];
...@@ -1679,6 +1743,8 @@ void TagDuel::RefreshExtra(int player, int flag, int use_cache) { ...@@ -1679,6 +1743,8 @@ void TagDuel::RefreshExtra(int player, int flag, int use_cache) {
BufferIO::WriteInt8(qbuf, LOCATION_EXTRA); BufferIO::WriteInt8(qbuf, LOCATION_EXTRA);
int len = query_field_card(pduel, player, LOCATION_EXTRA, flag, (unsigned char*)qbuf, use_cache); int len = query_field_card(pduel, player, LOCATION_EXTRA, flag, (unsigned char*)qbuf, use_cache);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, query_buffer, len + 3); NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
} }
void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) { void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) {
char query_buffer[0x2000]; char query_buffer[0x2000];
...@@ -1688,6 +1754,8 @@ void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) { ...@@ -1688,6 +1754,8 @@ void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) {
BufferIO::WriteInt8(qbuf, location); BufferIO::WriteInt8(qbuf, location);
BufferIO::WriteInt8(qbuf, sequence); BufferIO::WriteInt8(qbuf, sequence);
int len = query_card(pduel, player, location, sequence, flag, (unsigned char*)qbuf, 0); int len = query_card(pduel, player, location, sequence, flag, (unsigned char*)qbuf, 0);
ReplayPacket p((char*)query_buffer, len + 3);
replay_stream.push_back(p);
if(location & LOCATION_ONFIELD) { if(location & LOCATION_ONFIELD) {
int pid = (player == 0) ? 0 : 2; int pid = (player == 0) ? 0 : 2;
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 4); NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 4);
...@@ -1714,6 +1782,16 @@ void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) { ...@@ -1714,6 +1782,16 @@ void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) {
} }
} }
} }
void TagDuel::PseudoRefreshDeck(int player, int flag) {
char query_buffer[0x2000];
char* qbuf = query_buffer;
BufferIO::WriteInt8(qbuf, MSG_UPDATE_DATA);
BufferIO::WriteInt8(qbuf, player);
BufferIO::WriteInt8(qbuf, LOCATION_DECK);
int len = query_field_card(pduel, player, LOCATION_DECK, flag, (unsigned char*)qbuf, 0);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
}
int TagDuel::MessageHandler(long fduel, int type) { int TagDuel::MessageHandler(long fduel, int type) {
if(!enable_log) if(!enable_log)
return 0; return 0;
...@@ -1735,6 +1813,8 @@ void TagDuel::TagTimer(evutil_socket_t fd, short events, void* arg) { ...@@ -1735,6 +1813,8 @@ void TagDuel::TagTimer(evutil_socket_t fd, short events, void* arg) {
NetServer::ReSendToPlayer(sd->players[1]); NetServer::ReSendToPlayer(sd->players[1]);
NetServer::ReSendToPlayer(sd->players[2]); NetServer::ReSendToPlayer(sd->players[2]);
NetServer::ReSendToPlayer(sd->players[3]); NetServer::ReSendToPlayer(sd->players[3]);
ReplayPacket p((char*)wbuf, 3);
sd->replay_stream.push_back(p);
sd->EndDuel(); sd->EndDuel();
sd->DuelEndProc(); sd->DuelEndProc();
event_del(sd->etimer); event_del(sd->etimer);
......
...@@ -41,6 +41,9 @@ public: ...@@ -41,6 +41,9 @@ public:
static int MessageHandler(long fduel, int type); static int MessageHandler(long fduel, int type);
static void TagTimer(evutil_socket_t fd, short events, void* arg); static void TagTimer(evutil_socket_t fd, short events, void* arg);
void PseudoRefreshDeck(int player, int flag = 0x181fff);
static std::vector<ReplayPacket> replay_stream;
protected: protected:
DuelPlayer* players[4]; DuelPlayer* players[4];
DuelPlayer* pplayer[4]; DuelPlayer* pplayer[4];
...@@ -52,6 +55,7 @@ protected: ...@@ -52,6 +55,7 @@ protected:
unsigned char hand_result[2]; unsigned char hand_result[2];
unsigned char last_response; unsigned char last_response;
Replay last_replay; Replay last_replay;
Replay new_replay;
bool game_started; bool game_started;
unsigned char turn_count; unsigned char turn_count;
unsigned short time_limit[2]; unsigned short time_limit[2];
......
Subproject commit cbcff83c4001fb4208a530f580ad7ce0ac1fdfb2 Subproject commit 2a37a9fad5e84d06998e16eb530c0c2acdbb4e81
#The first line is used for comment #The first line is used for comment
#line doesn't start with '!' is also neglected #line doesn't start with '!' is also neglected
#called by DataManager::GetSysString(), DataManager::GetDesc()
#system #system
!system 1 Normal Summon !system 1 Normal Summon
!system 2 Special Summon !system 2 Special Summon
...@@ -375,6 +375,7 @@ ...@@ -375,6 +375,7 @@
!system 1353 Start at turn !system 1353 Start at turn
!system 1354 Hide Set Names  !system 1354 Hide Set Names 
!system 1355 Hide Chain Buttons !system 1355 Hide Chain Buttons
!system 1356 Old Replay Mode
!system 1360 Previous !system 1360 Previous
!system 1370 Level !system 1370 Level
!system 1371 Attack !system 1371 Attack
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment