Commit 22b3d51f authored by edo9300's avatar edo9300

Added support for yrp

parent 39327771
......@@ -28,6 +28,7 @@ mtrandom DuelClient::rnd;
std::vector<BufferIO::ReplayPacket> DuelClient::replay_stream;
Replay DuelClient::last_replay;
bool DuelClient::old_replay = true;
bool DuelClient::is_refreshing = false;
int DuelClient::match_kill = 0;
......@@ -735,6 +736,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->gMutex.Unlock();
match_kill = 0;
replay_stream.clear();
old_replay = true;
break;
}
case STOC_DUEL_END: {
......@@ -771,6 +773,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
break;
}
case STOC_REPLAY: {
if (!old_replay) break;
mainGame->gMutex.Lock();
mainGame->wPhase->setVisible(false);
if(mainGame->dInfo.player_type < 7)
......@@ -956,6 +959,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
break;
}
case STOC_NEW_REPLAY: {
old_replay = false;
mainGame->gMutex.Lock();
mainGame->wPhase->setVisible(false);
if(mainGame->dInfo.player_type < 7)
......@@ -994,7 +998,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
char* pbuf = msg;
wchar_t textBuffer[256];
if(!mainGame->dInfo.isReplay) {
if(!mainGame->dInfo.isReplay || mainGame->dInfo.isOldReplay) {
mainGame->dInfo.curMsg = BufferIO::ReadUInt8(pbuf);
if(mainGame->dInfo.curMsg != MSG_WAITING) {
BufferIO::ReplayPacket p;
......
......@@ -617,6 +617,7 @@ bool Game::Initialize() {
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);
stReplayInfo = env->addStaticText(L"", rect<s32>(360, 60, 570, 350), false, true, wReplay);
chkYrp = env->addCheckBox(false, recti(360, 250, 460, 270), wReplay, -1, dataManager.GetSysString(1999));
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->setTextAlignment(irr::gui::EGUIA_CENTER, irr::gui::EGUIA_CENTER);
......
......@@ -48,6 +48,7 @@ struct Config {
struct DuelInfo {
bool isStarted;
bool isReplay;
bool isOldReplay;
bool isReplaySkiping;
bool isFirst;
bool isTag;
......@@ -310,6 +311,7 @@ public:
irr::gui::IGUIWindow* wReplay;
irr::gui::IGUIListBox* lstReplayList;
irr::gui::IGUIStaticText* stReplayInfo;
irr::gui::IGUICheckBox* chkYrp;
irr::gui::IGUIButton* btnLoadReplay;
irr::gui::IGUIButton* btnReplayCancel;
irr::gui::IGUIEditBox* ebRepStartTurn;
......
......@@ -274,6 +274,8 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
if(!ReplayMode::cur_replay.OpenReplay(mainGame->lstReplayList->getListItem(mainGame->lstReplayList->getSelected())))
break;
}
if(mainGame->chkYrp->isChecked() && !ReplayMode::cur_replay.LoadYrp())
break;
mainGame->imgCard->setImage(imageManager.tCover[0]);
mainGame->wCardImg->setVisible(true);
mainGame->wInfos->setVisible(true);
......
#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 "../ocgcore/ocgapi.h"
#include "../ocgcore/card.h"
#include "../ocgcore/field.h"
#include <algorithm>
#include "lzma/LzmaLib.h"
......@@ -269,4 +270,31 @@ void Replay::Rewind() {
pdata = replay_data;
}
bool Replay::LoadYrp() {
if (pheader.flag & REPLAY_NEWREPLAY) {
pdata += (4 + ((pheader.flag & REPLAY_TAG) ? 160 : 80));
BufferIO::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 {
#define REPLAY_DECODED 0x4
#define REPLAY_SINGLE_MODE 0x8
#define REPLAY_LUA64 0x10
#define REPLAY_NEWREPLAY 0x20
struct ReplayHeader {
unsigned int id;
......@@ -42,12 +43,12 @@ public:
bool ReadNextPacket(BufferIO::ReplayPacket* packet);
bool ReadNextResponse(unsigned char resp[64]);
void ReadName(wchar_t* data);
void ReadHeader(ReplayHeader& header);
void ReadData(void* data, unsigned int length);
int ReadInt32();
short ReadInt16();
char ReadInt8();
void Rewind();
bool LoadYrp();
FILE* fp;
ReplayHeader pheader;
......
......@@ -9,6 +9,7 @@
namespace ygo {
long ReplayMode::pduel = 0;
bool ReplayMode::yrp = false;
Replay ReplayMode::cur_replay;
std::vector<BufferIO::ReplayPacket> ReplayMode::current_stream;
bool ReplayMode::is_continuing = true;
......@@ -25,8 +26,12 @@ int ReplayMode::skip_step = 0;
bool ReplayMode::StartReplay(int skipturn) {
skip_turn = skipturn;
if(skip_turn < 0)
skip_turn = 0;
Thread::NewThread(ReplayThread, 0);
skip_turn = 0;
yrp = cur_replay.pheader.id == 0x31707279;
if(yrp)
Thread::NewThread(OldReplayThread, 0);
else
Thread::NewThread(ReplayThread, 0);
return true;
}
void ReplayMode::StopReplay(bool is_exiting) {
......@@ -51,13 +56,6 @@ void ReplayMode::Pause(bool is_pause, bool is_step) {
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) {
const ReplayHeader& rh = cur_replay.pheader;
mainGame->dInfo.isFirst = true;
......@@ -123,6 +121,8 @@ int ReplayMode::ReplayThread(void* param) {
return 0;
}
void ReplayMode::EndDuel() {
if(yrp)
end_duel(pduel);
if(!is_closing) {
mainGame->actionSignal.Reset();
mainGame->gMutex.Lock();
......@@ -135,6 +135,7 @@ void ReplayMode::EndDuel() {
mainGame->gMutex.Lock();
mainGame->dInfo.isStarted = false;
mainGame->dInfo.isReplay = false;
mainGame->dInfo.isOldReplay = false;
mainGame->gMutex.Unlock();
mainGame->closeDoneSignal.Reset();
mainGame->closeSignal.Set();
......@@ -149,10 +150,17 @@ void ReplayMode::EndDuel() {
}
}
void ReplayMode::Restart(bool refresh) {
if(yrp) {
end_duel(pduel);
cur_replay.Rewind();
}
mainGame->dInfo.isStarted = false;
mainGame->dField.Clear();
mainGame->dInfo.tag_player[0] = false;
mainGame->dInfo.tag_player[1] = false;
if (yrp && !StartDuel()) {
EndDuel();
}
if(refresh) {
mainGame->dField.RefreshAllCards();
mainGame->dInfo.isStarted = true;
......
......@@ -12,6 +12,7 @@ namespace ygo {
class ReplayMode {
private:
static long pduel;
static bool yrp;
static bool is_continuing;
static bool is_closing;
static bool is_pausing;
......@@ -35,11 +36,23 @@ public:
static void Pause(bool is_pause, bool is_step);
static bool ReadReplayResponse();
static int ReplayThread(void* param);
static int OldReplayThread(void* param);
static bool StartDuel();
static void EndDuel();
static void Restart(bool refresh);
static void Undo();
static bool ReplayAnalyze(BufferIO::ReplayPacket p);
static bool ReplayAnalyze(char* msg, unsigned int len);
static void ReplayRefresh(int flag = 0xf81fff);
static void ReplayRefreshHand(int player, int flag = 0x781fff);
static void ReplayRefreshGrave(int player, int flag = 0x181fff);
static void ReplayRefreshDeck(int player, int flag = 0x181fff);
static void ReplayRefreshExtra(int player, int flag = 0x181fff);
static void ReplayRefreshSingle(int player, int location, int sequence, int flag = 0xf81fff);
static void ReplayReload();
static int MessageHandler(long fduel, int type);
};
}
......
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