Commit 6123e844 authored by edo9300's avatar edo9300

Added relay duel mode

parent b91f4976
...@@ -512,11 +512,17 @@ void Game::DrawMisc() { ...@@ -512,11 +512,17 @@ void Game::DrawMisc() {
recti p1size = mainGame->Resize(335, 31, 629, 50); recti p1size = mainGame->Resize(335, 31, 629, 50);
recti p2size = mainGame->Resize(986, 31, 986, 50); recti p2size = mainGame->Resize(986, 31, 986, 50);
if(!dInfo.isTag || !dInfo.tag_player[0]) if (dInfo.isRelay)
textFont->draw(dInfo.hostname_relay[dInfo.relay_player[0]], p1size, 0xffffffff, false, false, 0);
else if(!dInfo.isTag || !dInfo.tag_player[0])
textFont->draw(dInfo.hostname, p1size, 0xffffffff, false, false, 0); textFont->draw(dInfo.hostname, p1size, 0xffffffff, false, false, 0);
else else
textFont->draw(dInfo.hostname_tag, p1size, 0xffffffff, false, false, 0); textFont->draw(dInfo.hostname_tag, p1size, 0xffffffff, false, false, 0);
if(!dInfo.isTag || !dInfo.tag_player[1]) { if (dInfo.isRelay) {
auto cld = textFont->getDimension(dInfo.clientname_relay[dInfo.relay_player[1]]);
p2size.UpperLeftCorner.X -= cld.Width;
textFont->draw(dInfo.clientname_relay[dInfo.relay_player[1]], p2size, 0xffffffff, false, false, 0);
} else if(!dInfo.isTag || !dInfo.tag_player[1]) {
auto cld = textFont->getDimension(dInfo.clientname); auto cld = textFont->getDimension(dInfo.clientname);
p2size.UpperLeftCorner.X -= cld.Width; p2size.UpperLeftCorner.X -= cld.Width;
textFont->draw(dInfo.clientname, p2size, 0xffffffff, false, false, 0); textFont->draw(dInfo.clientname, p2size, 0xffffffff, false, false, 0);
......
...@@ -328,6 +328,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -328,6 +328,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->env->addMessageBox(L"", msgbuf); mainGame->env->addMessageBox(L"", msgbuf);
mainGame->cbDeckSelect->setEnabled(true); mainGame->cbDeckSelect->setEnabled(true);
mainGame->cbDeckSelect2->setEnabled(true); mainGame->cbDeckSelect2->setEnabled(true);
if(mainGame->dInfo.isTag || mainGame->dInfo.isRelay)
mainGame->btnHostPrepDuelist->setEnabled(true);
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
break; break;
} }
...@@ -554,20 +556,69 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -554,20 +556,69 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
str.append(msgbuf); str.append(msgbuf);
} }
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
if(pkt->info.mode == 2) { int x = (pkt->info.mode == 3) ? 60 : 0;
mainGame->btnHostPrepOB->setRelativePosition(rect<s32>(10, 180 + x, 110, 205 + x));
mainGame->stHostPrepOB->setRelativePosition(rect<s32>(10, 210 + x, 270, 230 + x));
mainGame->stHostPrepRule->setRelativePosition(rect<s32>(280, 30, 460, 230 + x));
mainGame->stDeckSelect->setRelativePosition(rect<s32>(10, 235 + x, 110, 255 + x));
mainGame->cbDeckSelect->setRelativePosition(rect<s32>(120, 230 + x, 270, 255 + x));
mainGame->cbDeckSelect2->setRelativePosition(rect<s32>(280, 230 + x, 430, 255 + x));
mainGame->btnHostPrepReady->setRelativePosition(rect<s32>(170, 180 + x, 270, 205 + x));
mainGame->btnHostPrepNotReady->setRelativePosition(rect<s32>(170, 180 + x, 270, 205 + x));
mainGame->btnHostPrepStart->setRelativePosition(rect<s32>(230, 280 + x, 340, 305 + x));
mainGame->btnHostPrepCancel->setRelativePosition(rect<s32>(350, 280 + x, 460, 305 + x));
mainGame->wHostPrepare->setRelativePosition(mainGame->ResizeWin(270, 120, 750, 440 + x));
mainGame->wHostPrepare2->setRelativePosition(mainGame->ResizeWin(750, 120, 950, 440 + x));
switch (pkt->info.mode) {
case 0:
case 1: {
mainGame->dInfo.isTag = false;
mainGame->dInfo.isRelay = false;
for (int i = 2; i < 6; i++) {
mainGame->chkHostPrepReady[i]->setVisible(false);
mainGame->stHostPrepDuelist[i]->setVisible(false);
}
break;
}
case 2:{
mainGame->dInfo.isTag = true; mainGame->dInfo.isTag = true;
mainGame->chkHostPrepReady[2]->setVisible(true); mainGame->dInfo.isRelay = false;
mainGame->chkHostPrepReady[3]->setVisible(true); for (int i = 2; i < 4; ++i) {
mainGame->stHostPrepDuelist[2]->setVisible(true); mainGame->stHostPrepDuelist[i]->setRelativePosition(rect<s32>(40, 75 + i * 25, 240, 95 + i * 25));
mainGame->stHostPrepDuelist[3]->setVisible(true); mainGame->btnHostPrepKick[i]->setRelativePosition(rect<s32>(10, 75 + i * 25, 30, 95 + i * 25));
} else { mainGame->chkHostPrepReady[i]->setRelativePosition(rect<s32>(250, 75 + i * 25, 270, 95 + i * 25));
}
for (int i = 2; i < 4; i++) {
mainGame->chkHostPrepReady[i]->setVisible(true);
mainGame->stHostPrepDuelist[i]->setVisible(true);
}
for (int i = 4; i < 6; i++) {
mainGame->chkHostPrepReady[i]->setVisible(false);
mainGame->stHostPrepDuelist[i]->setVisible(false);
}
break;
}
case 3: {
mainGame->dInfo.isTag = false; mainGame->dInfo.isTag = false;
mainGame->chkHostPrepReady[2]->setVisible(false); mainGame->dInfo.isRelay = true;
mainGame->chkHostPrepReady[3]->setVisible(false); for (int i = 0; i < 3; ++i) {
mainGame->stHostPrepDuelist[2]->setVisible(false); mainGame->stHostPrepDuelist[i]->setRelativePosition(rect<s32>(40, 65 + i * 25, 240, 85 + i * 25));
mainGame->stHostPrepDuelist[3]->setVisible(false); mainGame->btnHostPrepKick[i]->setRelativePosition(rect<s32>(10, 65 + i * 25, 30, 85 + i * 25));
mainGame->chkHostPrepReady[i]->setRelativePosition(rect<s32>(250, 65 + i * 25, 270, 85 + i * 25));
} }
for(int i = 0; i < 4; ++i) for (int i = 3; i < 6; ++i) {
mainGame->stHostPrepDuelist[i]->setRelativePosition(rect<s32>(40, 75 + i * 25, 240, 95 + i * 25));
mainGame->btnHostPrepKick[i]->setRelativePosition(rect<s32>(10, 75 + i * 25, 30, 95 + i * 25));
mainGame->chkHostPrepReady[i]->setRelativePosition(rect<s32>(250, 75 + i * 25, 270, 95 + i * 25));
}
for (int i = 2; i < 6; i++) {
mainGame->chkHostPrepReady[i]->setVisible(true);
mainGame->stHostPrepDuelist[i]->setVisible(true);
}
break;
}
}
for(int i = 0; i < 6; ++i)
mainGame->chkHostPrepReady[i]->setChecked(false); mainGame->chkHostPrepReady[i]->setChecked(false);
mainGame->btnHostPrepReady->setVisible(true); mainGame->btnHostPrepReady->setVisible(true);
mainGame->btnHostPrepNotReady->setVisible(false); mainGame->btnHostPrepNotReady->setVisible(false);
...@@ -584,6 +635,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -584,6 +635,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->stHostPrepDuelist[1]->setText(L""); mainGame->stHostPrepDuelist[1]->setText(L"");
mainGame->stHostPrepDuelist[2]->setText(L""); mainGame->stHostPrepDuelist[2]->setText(L"");
mainGame->stHostPrepDuelist[3]->setText(L""); mainGame->stHostPrepDuelist[3]->setText(L"");
mainGame->stHostPrepDuelist[4]->setText(L"");
mainGame->stHostPrepDuelist[5]->setText(L"");
mainGame->stHostPrepOB->setText(L""); mainGame->stHostPrepOB->setText(L"");
mainGame->SetStaticText(mainGame->stHostPrepRule, 180, mainGame->guiFont, (wchar_t*)str.c_str()); mainGame->SetStaticText(mainGame->stHostPrepRule, 180, mainGame->guiFont, (wchar_t*)str.c_str());
mainGame->SetStaticText(mainGame->stHostPrepRule2, 180, mainGame->guiFont, (wchar_t*)str2.c_str()); mainGame->SetStaticText(mainGame->stHostPrepRule2, 180, mainGame->guiFont, (wchar_t*)str2.c_str());
...@@ -613,11 +666,13 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -613,11 +666,13 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
} }
case STOC_TYPE_CHANGE: { case STOC_TYPE_CHANGE: {
STOC_TypeChange* pkt = (STOC_TypeChange*)pdata; STOC_TypeChange* pkt = (STOC_TypeChange*)pdata;
if(!mainGame->dInfo.isTag) { if(!mainGame->dInfo.isTag && !mainGame->dInfo.isRelay) {
selftype = pkt->type & 0xf; selftype = pkt->type & 0xf;
is_host = ((pkt->type >> 4) & 0xf) != 0; is_host = ((pkt->type >> 4) & 0xf) != 0;
mainGame->btnHostPrepKick[2]->setVisible(false); mainGame->btnHostPrepKick[2]->setVisible(false);
mainGame->btnHostPrepKick[3]->setVisible(false); mainGame->btnHostPrepKick[3]->setVisible(false);
mainGame->btnHostPrepKick[4]->setVisible(false);
mainGame->btnHostPrepKick[5]->setVisible(false);
if(is_host) { if(is_host) {
mainGame->btnHostPrepStart->setVisible(true); mainGame->btnHostPrepStart->setVisible(true);
mainGame->btnHostPrepKick[0]->setVisible(true); mainGame->btnHostPrepKick[0]->setVisible(true);
...@@ -647,7 +702,9 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -647,7 +702,9 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
} else { } else {
mainGame->btnHostPrepStart->setEnabled(false); mainGame->btnHostPrepStart->setEnabled(false);
} }
} else { } else if (mainGame->dInfo.isTag) {
mainGame->btnHostPrepKick[4]->setVisible(false);
mainGame->btnHostPrepKick[5]->setVisible(false);
if(selftype < 4) { if(selftype < 4) {
mainGame->chkHostPrepReady[selftype]->setEnabled(false); mainGame->chkHostPrepReady[selftype]->setEnabled(false);
mainGame->chkHostPrepReady[selftype]->setChecked(false); mainGame->chkHostPrepReady[selftype]->setChecked(false);
...@@ -680,6 +737,42 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -680,6 +737,42 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
} else { } else {
mainGame->btnHostPrepStart->setEnabled(false); mainGame->btnHostPrepStart->setEnabled(false);
} }
} else {
if (selftype < 6) {
mainGame->chkHostPrepReady[selftype]->setEnabled(false);
mainGame->chkHostPrepReady[selftype]->setChecked(false);
}
selftype = pkt->type & 0xf;
is_host = ((pkt->type >> 4) & 0xf) != 0;
mainGame->btnHostPrepDuelist->setEnabled(true);
if (is_host) {
mainGame->btnHostPrepStart->setVisible(true);
for (int i = 0; i < 6; ++i)
mainGame->btnHostPrepKick[i]->setVisible(true);
}
else {
mainGame->btnHostPrepStart->setVisible(false);
for (int i = 0; i < 6; ++i)
mainGame->btnHostPrepKick[i]->setVisible(false);
}
if (selftype < 6) {
mainGame->chkHostPrepReady[selftype]->setEnabled(true);
mainGame->btnHostPrepOB->setEnabled(true);
mainGame->btnHostPrepReady->setVisible(true);
mainGame->btnHostPrepNotReady->setVisible(false);
}
else {
mainGame->btnHostPrepOB->setEnabled(false);
mainGame->btnHostPrepReady->setVisible(false);
mainGame->btnHostPrepNotReady->setVisible(false);
}
if ((mainGame->chkHostPrepReady[0]->isChecked() || mainGame->chkHostPrepReady[1]->isChecked() || mainGame->chkHostPrepReady[2]->isChecked()) &&
(mainGame->chkHostPrepReady[3]->isChecked() || mainGame->chkHostPrepReady[4]->isChecked() || mainGame->chkHostPrepReady[5]->isChecked())) {
mainGame->btnHostPrepStart->setEnabled(true);
}
else {
mainGame->btnHostPrepStart->setEnabled(false);
}
} }
mainGame->dInfo.player_type = selftype; mainGame->dInfo.player_type = selftype;
break; break;
...@@ -699,6 +792,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -699,6 +792,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->dInfo.time_left[0] = 0; mainGame->dInfo.time_left[0] = 0;
mainGame->dInfo.time_left[1] = 0; mainGame->dInfo.time_left[1] = 0;
mainGame->dInfo.time_player = 2; mainGame->dInfo.time_player = 2;
mainGame->dInfo.relay_player[0] = 0;
mainGame->dInfo.relay_player[1] = 0;
mainGame->is_building = false; mainGame->is_building = false;
mainGame->wCardImg->setVisible(true); mainGame->wCardImg->setVisible(true);
mainGame->wInfos->setVisible(true); mainGame->wInfos->setVisible(true);
...@@ -717,7 +812,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -717,7 +812,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->wChat->setVisible(true); mainGame->wChat->setVisible(true);
mainGame->device->setEventReceiver(&mainGame->dField); mainGame->device->setEventReceiver(&mainGame->dField);
mainGame->SetPhaseButtons(); mainGame->SetPhaseButtons();
if(!mainGame->dInfo.isTag) { if(!mainGame->dInfo.isTag && !mainGame->dInfo.isRelay) {
if(selftype > 1) { if(selftype > 1) {
mainGame->dInfo.player_type = 7; mainGame->dInfo.player_type = 7;
mainGame->btnLeaveGame->setText(dataManager.GetSysString(1350)); mainGame->btnLeaveGame->setText(dataManager.GetSysString(1350));
...@@ -731,7 +826,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -731,7 +826,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
BufferIO::CopyWStr(mainGame->stHostPrepDuelist[1]->getText(), mainGame->dInfo.hostname, 20); BufferIO::CopyWStr(mainGame->stHostPrepDuelist[1]->getText(), mainGame->dInfo.hostname, 20);
BufferIO::CopyWStr(mainGame->stHostPrepDuelist[0]->getText(), mainGame->dInfo.clientname, 20); BufferIO::CopyWStr(mainGame->stHostPrepDuelist[0]->getText(), mainGame->dInfo.clientname, 20);
} }
} else { } else if(mainGame->dInfo.isTag) {
if(selftype > 3) { if(selftype > 3) {
mainGame->dInfo.player_type = 7; mainGame->dInfo.player_type = 7;
mainGame->btnLeaveGame->setText(dataManager.GetSysString(1350)); mainGame->btnLeaveGame->setText(dataManager.GetSysString(1350));
...@@ -751,6 +846,32 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -751,6 +846,32 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
} }
mainGame->dInfo.tag_player[0] = false; mainGame->dInfo.tag_player[0] = false;
mainGame->dInfo.tag_player[1] = false; mainGame->dInfo.tag_player[1] = false;
} else {
if(selftype > 5) {
mainGame->dInfo.player_type = 7;
mainGame->btnLeaveGame->setText(dataManager.GetSysString(1350));
mainGame->btnLeaveGame->setVisible(true);
mainGame->btnSpectatorSwap->setVisible(true);
}
if(selftype > 2 && selftype < 6) {
for (int i = 2; i >= 0; i--) {
if (mainGame->chkHostPrepReady[i + 3]->isChecked())
mainGame->dInfo.relay_player[0] = i;
if (mainGame->chkHostPrepReady[i]->isChecked())
mainGame->dInfo.relay_player[1] = i;
BufferIO::CopyWStr(mainGame->stHostPrepDuelist[i + 3]->getText(), mainGame->dInfo.hostname_relay[0], 20);
BufferIO::CopyWStr(mainGame->stHostPrepDuelist[i]->getText(), mainGame->dInfo.clientname_relay[1], 20);
}
} else {
for (int i = 2; i >= 0; i--) {
if(mainGame->chkHostPrepReady[i]->isChecked())
mainGame->dInfo.relay_player[0] = i;
if(mainGame->chkHostPrepReady[i + 3]->isChecked())
mainGame->dInfo.relay_player[1] = i;
BufferIO::CopyWStr(mainGame->stHostPrepDuelist[i]->getText(), mainGame->dInfo.hostname_relay[0], 20);
BufferIO::CopyWStr(mainGame->stHostPrepDuelist[i + 3]->getText(), mainGame->dInfo.clientname_relay[1], 20);
}
}
} }
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
match_kill = 0; match_kill = 0;
...@@ -890,11 +1011,16 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -890,11 +1011,16 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
case STOC_HS_PLAYER_ENTER: { case STOC_HS_PLAYER_ENTER: {
mainGame->PlaySoundEffect("./sound/playerenter.wav"); mainGame->PlaySoundEffect("./sound/playerenter.wav");
STOC_HS_PlayerEnter* pkt = (STOC_HS_PlayerEnter*)pdata; STOC_HS_PlayerEnter* pkt = (STOC_HS_PlayerEnter*)pdata;
if(pkt->pos > 3) if(pkt->pos > 5)
break; break;
wchar_t name[20]; wchar_t name[20];
BufferIO::CopyWStr(pkt->name, name, 20); BufferIO::CopyWStr(pkt->name, name, 20);
if(mainGame->dInfo.isTag) { if (mainGame->dInfo.isRelay) {
if (pkt->pos < 3)
BufferIO::CopyWStr(pkt->name, mainGame->dInfo.hostname_relay[pkt->pos], 20);
else
BufferIO::CopyWStr(pkt->name, mainGame->dInfo.clientname_relay[pkt->pos - 3], 20);
} else if(mainGame->dInfo.isTag) {
if(pkt->pos == 0) if(pkt->pos == 0)
BufferIO::CopyWStr(pkt->name, mainGame->dInfo.hostname, 20); BufferIO::CopyWStr(pkt->name, mainGame->dInfo.hostname, 20);
else if(pkt->pos == 1) else if(pkt->pos == 1)
...@@ -918,7 +1044,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -918,7 +1044,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
STOC_HS_PlayerChange* pkt = (STOC_HS_PlayerChange*)pdata; STOC_HS_PlayerChange* pkt = (STOC_HS_PlayerChange*)pdata;
unsigned char pos = (pkt->status >> 4) & 0xf; unsigned char pos = (pkt->status >> 4) & 0xf;
unsigned char state = pkt->status & 0xf; unsigned char state = pkt->status & 0xf;
if(pos > 3) if(pos > 5)
break; break;
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
if(state < 8) { if(state < 8) {
...@@ -927,14 +1053,21 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -927,14 +1053,21 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->stHostPrepDuelist[state]->setText(prename); mainGame->stHostPrepDuelist[state]->setText(prename);
mainGame->stHostPrepDuelist[pos]->setText(L""); mainGame->stHostPrepDuelist[pos]->setText(L"");
mainGame->chkHostPrepReady[pos]->setChecked(false); mainGame->chkHostPrepReady[pos]->setChecked(false);
if(pos == 0) if (mainGame->dInfo.isRelay) {
if (pos < 3)
BufferIO::CopyWStr(prename, mainGame->dInfo.hostname_relay[pos], 20);
else
BufferIO::CopyWStr(prename, mainGame->dInfo.clientname_relay[pos - 3], 20);
} else {
if (pos == 0)
BufferIO::CopyWStr(prename, mainGame->dInfo.hostname, 20); BufferIO::CopyWStr(prename, mainGame->dInfo.hostname, 20);
else if(pos == 1) else if (pos == 1)
BufferIO::CopyWStr(prename, mainGame->dInfo.hostname_tag, 20); BufferIO::CopyWStr(prename, mainGame->dInfo.hostname_tag, 20);
else if(pos == 2) else if (pos == 2)
BufferIO::CopyWStr(prename, mainGame->dInfo.clientname, 20); BufferIO::CopyWStr(prename, mainGame->dInfo.clientname, 20);
else if(pos == 3) else if (pos == 3)
BufferIO::CopyWStr(prename, mainGame->dInfo.clientname_tag, 20); BufferIO::CopyWStr(prename, mainGame->dInfo.clientname_tag, 20);
}
} else if(state == PLAYERCHANGE_READY) { } else if(state == PLAYERCHANGE_READY) {
mainGame->chkHostPrepReady[pos]->setChecked(true); mainGame->chkHostPrepReady[pos]->setChecked(true);
if(pos == selftype) { if(pos == selftype) {
...@@ -958,8 +1091,10 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -958,8 +1091,10 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->chkHostPrepReady[pos]->setChecked(false); mainGame->chkHostPrepReady[pos]->setChecked(false);
mainGame->stHostPrepOB->setText(watchbuf); mainGame->stHostPrepOB->setText(watchbuf);
} }
if(mainGame->chkHostPrepReady[0]->isChecked() && mainGame->chkHostPrepReady[1]->isChecked() if((mainGame->chkHostPrepReady[0]->isChecked() && mainGame->chkHostPrepReady[1]->isChecked()
&& (!mainGame->dInfo.isTag || (mainGame->chkHostPrepReady[2]->isChecked() && mainGame->chkHostPrepReady[3]->isChecked()))) { && (!mainGame->dInfo.isTag || (mainGame->chkHostPrepReady[2]->isChecked() && mainGame->chkHostPrepReady[3]->isChecked()))) ||
(mainGame->dInfo.isRelay && ((mainGame->chkHostPrepReady[0]->isChecked() || mainGame->chkHostPrepReady[1]->isChecked() || mainGame->chkHostPrepReady[2]->isChecked()) &&
(mainGame->chkHostPrepReady[3]->isChecked() || mainGame->chkHostPrepReady[4]->isChecked() || mainGame->chkHostPrepReady[5]->isChecked())))){
mainGame->btnHostPrepStart->setEnabled(true); mainGame->btnHostPrepStart->setEnabled(true);
} else { } else {
mainGame->btnHostPrepStart->setEnabled(false); mainGame->btnHostPrepStart->setEnabled(false);
...@@ -1181,7 +1316,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -1181,7 +1316,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
if(match_kill) if(match_kill)
myswprintf(vic_buf, dataManager.GetVictoryString(0x20), dataManager.GetName(match_kill)); myswprintf(vic_buf, dataManager.GetVictoryString(0x20), dataManager.GetName(match_kill));
else if(type < 0x10) else if(type < 0x10)
myswprintf(vic_buf, L"[%ls] %ls", mainGame->dInfo.clientname, dataManager.GetVictoryString(type)); myswprintf(vic_buf, L"[%ls] %ls", (mainGame->dInfo.isRelay) ? mainGame->dInfo.clientname_relay[mainGame->dInfo.relay_player[1]] : mainGame->dInfo.clientname, dataManager.GetVictoryString(type));
else else
myswprintf(vic_buf, L"%ls", dataManager.GetVictoryString(type)); myswprintf(vic_buf, L"%ls", dataManager.GetVictoryString(type));
mainGame->dInfo.vic_string = vic_buf; mainGame->dInfo.vic_string = vic_buf;
...@@ -1190,7 +1325,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -1190,7 +1325,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
if(match_kill) if(match_kill)
myswprintf(vic_buf, dataManager.GetVictoryString(0x20), dataManager.GetName(match_kill)); myswprintf(vic_buf, dataManager.GetVictoryString(0x20), dataManager.GetName(match_kill));
else if(type < 0x10) else if(type < 0x10)
myswprintf(vic_buf, L"[%ls] %ls", mainGame->dInfo.hostname, dataManager.GetVictoryString(type)); myswprintf(vic_buf, L"[%ls] %ls", (mainGame->dInfo.isRelay) ? mainGame->dInfo.hostname_relay[mainGame->dInfo.relay_player[0]] : mainGame->dInfo.hostname, dataManager.GetVictoryString(type));
else else
myswprintf(vic_buf, L"%ls", dataManager.GetVictoryString(type)); myswprintf(vic_buf, L"%ls", dataManager.GetVictoryString(type));
mainGame->dInfo.vic_string = vic_buf; mainGame->dInfo.vic_string = vic_buf;
...@@ -1223,7 +1358,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -1223,7 +1358,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
} }
if(playertype & 0xf0) if(playertype & 0xf0)
mainGame->dInfo.player_type = 7; mainGame->dInfo.player_type = 7;
if(mainGame->dInfo.isTag) { if(mainGame->dInfo.isTag && !mainGame->dInfo.isRelay) {
if(mainGame->dInfo.isFirst) if(mainGame->dInfo.isFirst)
mainGame->dInfo.tag_player[1] = true; mainGame->dInfo.tag_player[1] = true;
else else
...@@ -2456,7 +2591,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -2456,7 +2591,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
mainGame->btnCancelOrFinish->setVisible(false); mainGame->btnCancelOrFinish->setVisible(false);
} }
} }
if(mainGame->dInfo.isTag && mainGame->dInfo.turn != 1) { if(!mainGame->dInfo.isRelay && mainGame->dInfo.isTag && mainGame->dInfo.turn != 1) {
if(player == 0) if(player == 0)
mainGame->dInfo.tag_player[0] = !mainGame->dInfo.tag_player[0]; mainGame->dInfo.tag_player[0] = !mainGame->dInfo.tag_player[0];
else else
...@@ -3667,7 +3802,13 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -3667,7 +3802,13 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
return true; return true;
} }
case MSG_TAG_SWAP: { case MSG_TAG_SWAP: {
int player = mainGame->LocalPlayer(BufferIO::ReadInt8(pbuf)); int player = BufferIO::ReadInt8(pbuf);
int newp = 0;
if (mainGame->dInfo.isRelay) {
newp = player >> 4;
player = mainGame->LocalPlayer(player & 0xf);
} else
player = mainGame->LocalPlayer(player);
size_t mcount = (size_t)BufferIO::ReadInt8(pbuf); size_t mcount = (size_t)BufferIO::ReadInt8(pbuf);
size_t ecount = (size_t)BufferIO::ReadInt8(pbuf); size_t ecount = (size_t)BufferIO::ReadInt8(pbuf);
size_t pcount = (size_t)BufferIO::ReadInt8(pbuf); size_t pcount = (size_t)BufferIO::ReadInt8(pbuf);
...@@ -3777,6 +3918,8 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -3777,6 +3918,8 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
} }
mainGame->WaitFrameSignal(5); mainGame->WaitFrameSignal(5);
} }
if(mainGame->dInfo.isRelay)
mainGame->dInfo.relay_player[player] = newp;
break; break;
} }
case MSG_RELOAD_FIELD: { case MSG_RELOAD_FIELD: {
......
...@@ -1848,12 +1848,16 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -1848,12 +1848,16 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
if(mplayer >= 0) { if(mplayer >= 0) {
const wchar_t* player_name; const wchar_t* player_name;
if(mplayer == 0) { if(mplayer == 0) {
if(!mainGame->dInfo.isTag || !mainGame->dInfo.tag_player[0]) if(mainGame->dInfo.isRelay)
player_name = mainGame->dInfo.hostname_relay[mainGame->dInfo.relay_player[0]];
else if(!mainGame->dInfo.isTag || !mainGame->dInfo.tag_player[0])
player_name = mainGame->dInfo.hostname; player_name = mainGame->dInfo.hostname;
else else
player_name = mainGame->dInfo.hostname_tag; player_name = mainGame->dInfo.hostname_tag;
} else { } else {
if(!mainGame->dInfo.isTag || !mainGame->dInfo.tag_player[1]) if (mainGame->dInfo.isRelay)
player_name = mainGame->dInfo.clientname_relay[mainGame->dInfo.relay_player[1]];
else if(!mainGame->dInfo.isTag || !mainGame->dInfo.tag_player[1])
player_name = mainGame->dInfo.clientname; player_name = mainGame->dInfo.clientname;
else else
player_name = mainGame->dInfo.clientname_tag; player_name = mainGame->dInfo.clientname_tag;
......
...@@ -155,6 +155,7 @@ bool Game::Initialize() { ...@@ -155,6 +155,7 @@ bool Game::Initialize() {
cbMatchMode->addItem(dataManager.GetSysString(1244)); cbMatchMode->addItem(dataManager.GetSysString(1244));
cbMatchMode->addItem(dataManager.GetSysString(1245)); cbMatchMode->addItem(dataManager.GetSysString(1245));
cbMatchMode->addItem(dataManager.GetSysString(1246)); cbMatchMode->addItem(dataManager.GetSysString(1246));
cbMatchMode->addItem(dataManager.GetSysString(1247));
env->addStaticText(dataManager.GetSysString(1237), rect<s32>(20, 120, 320, 140), false, false, wCreateHost); env->addStaticText(dataManager.GetSysString(1237), rect<s32>(20, 120, 320, 140), false, false, wCreateHost);
myswprintf(strbuf, L"%d", 180); myswprintf(strbuf, L"%d", 180);
ebTimeLimit = env->addEditBox(strbuf, rect<s32>(140, 115, 220, 140), true, wCreateHost); ebTimeLimit = env->addEditBox(strbuf, rect<s32>(140, 115, 220, 140), true, wCreateHost);
...@@ -237,23 +238,17 @@ bool Game::Initialize() { ...@@ -237,23 +238,17 @@ bool Game::Initialize() {
wHostPrepare2->setVisible(false); wHostPrepare2->setVisible(false);
stHostPrepRule2 = env->addStaticText(L"", rect<s32>(10, 30, 460, 350), false, true, wHostPrepare2); stHostPrepRule2 = env->addStaticText(L"", rect<s32>(10, 30, 460, 350), false, true, wHostPrepare2);
btnHostPrepDuelist = env->addButton(rect<s32>(10, 30, 110, 55), wHostPrepare, BUTTON_HP_DUELIST, dataManager.GetSysString(1251)); btnHostPrepDuelist = env->addButton(rect<s32>(10, 30, 110, 55), wHostPrepare, BUTTON_HP_DUELIST, dataManager.GetSysString(1251));
for(int i = 0; i < 2; ++i) { for(int i = 0; i < 6; ++i) {
stHostPrepDuelist[i] = env->addStaticText(L"", rect<s32>(40, 65 + i * 25, 240, 85 + i * 25), true, false, wHostPrepare); stHostPrepDuelist[i] = env->addStaticText(L"", rect<s32>(40, 65 + i * 25, 240, 85 + i * 25), true, false, wHostPrepare);
btnHostPrepKick[i] = env->addButton(rect<s32>(10, 65 + i * 25, 30, 85 + i * 25), wHostPrepare, BUTTON_HP_KICK, L"X"); btnHostPrepKick[i] = env->addButton(rect<s32>(10, 65 + i * 25, 30, 85 + i * 25), wHostPrepare, BUTTON_HP_KICK, L"X");
chkHostPrepReady[i] = env->addCheckBox(false, rect<s32>(250, 65 + i * 25, 270, 85 + i * 25), wHostPrepare, CHECKBOX_HP_READY, L""); chkHostPrepReady[i] = env->addCheckBox(false, rect<s32>(250, 65 + i * 25, 270, 85 + i * 25), wHostPrepare, CHECKBOX_HP_READY, L"");
chkHostPrepReady[i]->setEnabled(false); chkHostPrepReady[i]->setEnabled(false);
} }
for(int i = 2; i < 4; ++i) {
stHostPrepDuelist[i] = env->addStaticText(L"", rect<s32>(40, 75 + i * 25, 240, 95 + i * 25), true, false, wHostPrepare);
btnHostPrepKick[i] = env->addButton(rect<s32>(10, 75 + i * 25, 30, 95 + i * 25), wHostPrepare, BUTTON_HP_KICK, L"X");
chkHostPrepReady[i] = env->addCheckBox(false, rect<s32>(250, 75 + i * 25, 270, 95 + i * 25), wHostPrepare, CHECKBOX_HP_READY, L"");
chkHostPrepReady[i]->setEnabled(false);
}
btnHostPrepOB = env->addButton(rect<s32>(10, 180, 110, 205), wHostPrepare, BUTTON_HP_OBSERVER, dataManager.GetSysString(1252)); btnHostPrepOB = env->addButton(rect<s32>(10, 180, 110, 205), wHostPrepare, BUTTON_HP_OBSERVER, dataManager.GetSysString(1252));
myswprintf(dataManager.strBuffer, L"%ls%d", dataManager.GetSysString(1253), 0); myswprintf(dataManager.strBuffer, L"%ls%d", dataManager.GetSysString(1253), 0);
stHostPrepOB = env->addStaticText(dataManager.strBuffer, rect<s32>(10, 210, 270, 230), false, false, wHostPrepare); stHostPrepOB = env->addStaticText(dataManager.strBuffer, rect<s32>(10, 210, 270, 230), false, false, wHostPrepare);
stHostPrepRule = env->addStaticText(L"", rect<s32>(280, 30, 460, 230), false, true, wHostPrepare); stHostPrepRule = env->addStaticText(L"", rect<s32>(280, 30, 460, 230), false, true, wHostPrepare);
env->addStaticText(dataManager.GetSysString(1254), rect<s32>(10, 235, 110, 255), false, false, wHostPrepare); stDeckSelect = env->addStaticText(dataManager.GetSysString(1254), rect<s32>(10, 235, 110, 255), false, false, wHostPrepare);
cbDeckSelect = env->addComboBox(rect<s32>(120, 230, 270, 255), wHostPrepare); cbDeckSelect = env->addComboBox(rect<s32>(120, 230, 270, 255), wHostPrepare);
cbDeckSelect->setMaxSelectionRows(10); cbDeckSelect->setMaxSelectionRows(10);
cbDeckSelect2 = env->addComboBox(rect<s32>(280, 230, 430, 255), wHostPrepare); cbDeckSelect2 = env->addComboBox(rect<s32>(280, 230, 430, 255), wHostPrepare);
...@@ -1362,22 +1357,22 @@ void Game::AddChatMsg(wchar_t* msg, int player) { ...@@ -1362,22 +1357,22 @@ void Game::AddChatMsg(wchar_t* msg, int player) {
chatType[0] = player; chatType[0] = player;
switch(player) { switch(player) {
case 0: //from host case 0: //from host
chatMsg[0].append(dInfo.hostname); chatMsg[0].append((dInfo.isRelay) ? dInfo.hostname_relay[0] : dInfo.hostname);
chatMsg[0].append(L": "); chatMsg[0].append(L": ");
break; break;
case 1: //from client case 1: //from client
PlaySoundEffect("./sound/chatmessage.wav"); PlaySoundEffect("./sound/chatmessage.wav");
chatMsg[0].append(dInfo.clientname); chatMsg[0].append((dInfo.isRelay) ? dInfo.clientname_relay[0] : dInfo.clientname);
chatMsg[0].append(L": "); chatMsg[0].append(L": ");
break; break;
case 2: //host tag case 2: //host tag
PlaySoundEffect("./sound/chatmessage.wav"); PlaySoundEffect("./sound/chatmessage.wav");
chatMsg[0].append(dInfo.hostname_tag); chatMsg[0].append((dInfo.isRelay) ? dInfo.hostname_relay[1] : dInfo.hostname_tag);
chatMsg[0].append(L": "); chatMsg[0].append(L": ");
break; break;
case 3: //client tag case 3: //client tag
PlaySoundEffect("./sound/chatmessage.wav"); PlaySoundEffect("./sound/chatmessage.wav");
chatMsg[0].append(dInfo.clientname_tag); chatMsg[0].append((dInfo.isRelay) ? dInfo.clientname_relay[1] : dInfo.clientname_tag);
chatMsg[0].append(L": "); chatMsg[0].append(L": ");
break; break;
case 7: //local name case 7: //local name
...@@ -1662,8 +1657,13 @@ void Game::OnResize() { ...@@ -1662,8 +1657,13 @@ void Game::OnResize() {
wLanWindow->setRelativePosition(ResizeWin(220, 100, 800, 520)); wLanWindow->setRelativePosition(ResizeWin(220, 100, 800, 520));
wCreateHost->setRelativePosition(ResizeWin(320, 100, 700, 520)); wCreateHost->setRelativePosition(ResizeWin(320, 100, 700, 520));
if (dInfo.isRelay) {
wHostPrepare->setRelativePosition(ResizeWin(270, 120, 750, 500));
wHostPrepare2->setRelativePosition(ResizeWin(750, 120, 950, 500));
} else {
wHostPrepare->setRelativePosition(ResizeWin(270, 120, 750, 440)); wHostPrepare->setRelativePosition(ResizeWin(270, 120, 750, 440));
wHostPrepare2->setRelativePosition(ResizeWin(750, 120, 950, 440)); wHostPrepare2->setRelativePosition(ResizeWin(750, 120, 950, 440));
}
wRules->setRelativePosition(ResizeWin(630, 100, 1000, 310)); wRules->setRelativePosition(ResizeWin(630, 100, 1000, 310));
wCustomRules->setRelativePosition(ResizeWin(700, 100, 910, 410)); wCustomRules->setRelativePosition(ResizeWin(700, 100, 910, 410));
wReplay->setRelativePosition(ResizeWin(220, 100, 800, 520)); wReplay->setRelativePosition(ResizeWin(220, 100, 800, 520));
......
...@@ -52,10 +52,12 @@ struct DuelInfo { ...@@ -52,10 +52,12 @@ struct DuelInfo {
bool isReplaySkiping; bool isReplaySkiping;
bool isFirst; bool isFirst;
bool isTag; bool isTag;
bool isRelay;
bool isSingleMode; bool isSingleMode;
bool lua64; bool lua64;
bool is_shuffling; bool is_shuffling;
bool tag_player[2]; bool tag_player[2];
int relay_player[2];
int lp[2]; int lp[2];
int startlp; int startlp;
int duel_field; int duel_field;
...@@ -66,6 +68,8 @@ struct DuelInfo { ...@@ -66,6 +68,8 @@ struct DuelInfo {
wchar_t clientname[20]; wchar_t clientname[20];
wchar_t hostname_tag[20]; wchar_t hostname_tag[20];
wchar_t clientname_tag[20]; wchar_t clientname_tag[20];
wchar_t clientname_relay[3][20];
wchar_t hostname_relay[3][20];
wchar_t strLP[2][16]; wchar_t strLP[2][16];
wchar_t* vic_string; wchar_t* vic_string;
unsigned char player_type; unsigned char player_type;
...@@ -301,14 +305,15 @@ public: ...@@ -301,14 +305,15 @@ public:
irr::gui::IGUIStaticText* stHostCardRule; irr::gui::IGUIStaticText* stHostCardRule;
irr::gui::IGUIButton* btnHostPrepDuelist; irr::gui::IGUIButton* btnHostPrepDuelist;
irr::gui::IGUIButton* btnHostPrepOB; irr::gui::IGUIButton* btnHostPrepOB;
irr::gui::IGUIStaticText* stHostPrepDuelist[4]; irr::gui::IGUIStaticText* stHostPrepDuelist[6];
irr::gui::IGUICheckBox* chkHostPrepReady[4]; irr::gui::IGUICheckBox* chkHostPrepReady[6];
irr::gui::IGUIButton* btnHostPrepKick[4]; irr::gui::IGUIButton* btnHostPrepKick[6];
irr::gui::IGUIComboBox* cbDeckSelect; irr::gui::IGUIComboBox* cbDeckSelect;
irr::gui::IGUIComboBox* cbDeckSelect2; irr::gui::IGUIComboBox* cbDeckSelect2;
irr::gui::IGUIStaticText* stHostPrepRule; irr::gui::IGUIStaticText* stHostPrepRule;
irr::gui::IGUIStaticText* stHostPrepRule2; irr::gui::IGUIStaticText* stHostPrepRule2;
irr::gui::IGUIStaticText* stHostPrepOB; irr::gui::IGUIStaticText* stHostPrepOB;
irr::gui::IGUIStaticText* stDeckSelect;
irr::gui::IGUIButton* btnHostPrepReady; irr::gui::IGUIButton* btnHostPrepReady;
irr::gui::IGUIButton* btnHostPrepNotReady; irr::gui::IGUIButton* btnHostPrepNotReady;
irr::gui::IGUIButton* btnHostPrepStart; irr::gui::IGUIButton* btnHostPrepStart;
......
...@@ -226,11 +226,17 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -226,11 +226,17 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
UpdateDeck(); UpdateDeck();
DuelClient::SendPacketToServer(CTOS_HS_READY); DuelClient::SendPacketToServer(CTOS_HS_READY);
mainGame->cbDeckSelect->setEnabled(false); mainGame->cbDeckSelect->setEnabled(false);
mainGame->cbDeckSelect2->setEnabled(false);
if(mainGame->dInfo.isTag || mainGame->dInfo.isRelay)
mainGame->btnHostPrepDuelist->setEnabled(false);
break; break;
} }
case BUTTON_HP_NOTREADY: { case BUTTON_HP_NOTREADY: {
DuelClient::SendPacketToServer(CTOS_HS_NOTREADY); DuelClient::SendPacketToServer(CTOS_HS_NOTREADY);
mainGame->cbDeckSelect->setEnabled(true); mainGame->cbDeckSelect->setEnabled(true);
mainGame->cbDeckSelect2->setEnabled(true);
if(mainGame->dInfo.isTag || mainGame->dInfo.isRelay)
mainGame->btnHostPrepDuelist->setEnabled(true);
break; break;
} }
case BUTTON_HP_START: { case BUTTON_HP_START: {
...@@ -425,10 +431,14 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -425,10 +431,14 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
DuelClient::SendPacketToServer(CTOS_HS_READY); DuelClient::SendPacketToServer(CTOS_HS_READY);
mainGame->cbDeckSelect->setEnabled(false); mainGame->cbDeckSelect->setEnabled(false);
mainGame->cbDeckSelect2->setEnabled(false); mainGame->cbDeckSelect2->setEnabled(false);
if(mainGame->dInfo.isTag || mainGame->dInfo.isRelay)
mainGame->btnHostPrepDuelist->setEnabled(false);
} else { } else {
DuelClient::SendPacketToServer(CTOS_HS_NOTREADY); DuelClient::SendPacketToServer(CTOS_HS_NOTREADY);
mainGame->cbDeckSelect->setEnabled(true); mainGame->cbDeckSelect->setEnabled(true);
mainGame->cbDeckSelect2->setEnabled(true); mainGame->cbDeckSelect2->setEnabled(true);
if(mainGame->dInfo.isTag || mainGame->dInfo.isRelay)
mainGame->btnHostPrepDuelist->setEnabled(true);
} }
break; break;
} }
......
#include "netserver.h" #include "netserver.h"
#include "single_duel.h" #include "single_duel.h"
#include "tag_duel.h" #include "tag_duel.h"
#include "relay_duel.h"
namespace ygo { namespace ygo {
std::unordered_map<bufferevent*, DuelPlayer> NetServer::users; std::unordered_map<bufferevent*, DuelPlayer> NetServer::users;
...@@ -232,10 +233,13 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, char* data, unsigned int len) { ...@@ -232,10 +233,13 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, char* data, unsigned int len) {
} else if(pkt->info.mode == MODE_TAG) { } else if(pkt->info.mode == MODE_TAG) {
duel_mode = new TagDuel(); duel_mode = new TagDuel();
duel_mode->etimer = event_new(net_evbase, 0, EV_TIMEOUT | EV_PERSIST, TagDuel::TagTimer, duel_mode); duel_mode->etimer = event_new(net_evbase, 0, EV_TIMEOUT | EV_PERSIST, TagDuel::TagTimer, duel_mode);
} else if(pkt->info.mode == MODE_RELAY) {
duel_mode = new RelayDuel();
duel_mode->etimer = event_new(net_evbase, 0, EV_TIMEOUT | EV_PERSIST, RelayDuel::RelayTimer, duel_mode);
} }
if(pkt->info.rule > 3) if(pkt->info.rule > 3)
pkt->info.rule = 0; pkt->info.rule = 0;
if(pkt->info.mode > 2) if(pkt->info.mode > 3)
pkt->info.mode = 0; pkt->info.mode = 0;
unsigned int hash = 1; unsigned int hash = 1;
for(auto lfit = deckManager._lfList.begin(); lfit != deckManager._lfList.end(); ++lfit) { for(auto lfit = deckManager._lfList.begin(); lfit != deckManager._lfList.end(); ++lfit) {
......
...@@ -241,4 +241,5 @@ public: ...@@ -241,4 +241,5 @@ public:
#define MODE_SINGLE 0x0 #define MODE_SINGLE 0x0
#define MODE_MATCH 0x1 #define MODE_MATCH 0x1
#define MODE_TAG 0x2 #define MODE_TAG 0x2
#define MODE_RELAY 0x3
#endif //NETWORK_H #endif //NETWORK_H
#include "relay_duel.h"
#include "netserver.h"
#include "game.h"
#include "../ocgcore/ocgapi.h"
#include "../ocgcore/card.h"
#include "../ocgcore/duel.h"
#include "../ocgcore/field.h"
#include "../ocgcore/mtrandom.h"
namespace ygo {
std::vector<ReplayPacket> RelayDuel::replay_stream;
RelayDuel::RelayDuel() {
game_started = false;
for (int i = 0; i < 6; i++)
players[i] = duelist();
startp[0] = 0;
startp[1] = 3;
}
RelayDuel::~RelayDuel() {
}
void RelayDuel::Chat(DuelPlayer* dp, void* pdata, int len) {
STOC_Chat scc;
scc.player = dp->type;
unsigned short* msg = (unsigned short*)pdata;
int msglen = BufferIO::CopyWStr(msg, scc.msg, 256);
for(int i = 0; i < 6; i++)
if(players[i].player != dp)
NetServer::SendBufferToPlayer(players[i].player, STOC_CHAT, &scc, 4 + msglen * 2);
}
void RelayDuel::JoinGame(DuelPlayer* dp, void* pdata, bool is_creater) {
if(!is_creater) {
if(dp->game && dp->type != 0xff) {
STOC_ErrorMsg scem;
scem.msg = ERRMSG_JOINERROR;
scem.code = 0;
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
NetServer::DisconnectPlayer(dp);
return;
}
CTOS_JoinGame* pkt = (CTOS_JoinGame*)pdata;
if(pkt->version != PRO_VERSION) {
STOC_ErrorMsg scem;
scem.msg = ERRMSG_VERERROR;
scem.code = PRO_VERSION;
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
NetServer::DisconnectPlayer(dp);
return;
}
wchar_t jpass[20];
BufferIO::CopyWStr(pkt->pass, jpass, 20);
if(wcscmp(jpass, pass)) {
STOC_ErrorMsg scem;
scem.msg = ERRMSG_JOINERROR;
scem.code = 1;
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
return;
}
}
dp->game = this;
if(!players[0].player && !players[1].player && !players[2].player &&
!players[3].player && !players[4].player && !players[5].player && observers.size() == 0)
host_player = dp;
STOC_JoinGame scjg;
scjg.info = host_info;
STOC_TypeChange sctc;
sctc.type = (host_player == dp) ? 0x10 : 0;
if(!players[0].player || !players[1].player || !players[2].player ||
!players[3].player || !players[4].player || !players[5].player) {
STOC_HS_PlayerEnter scpe;
BufferIO::CopyWStr(dp->name, scpe.name, 20);
for (int i = 0; i < 6; i++)
if (!players[i].player) {
scpe.pos = i;
break;
}
for (int i = 0; i < 6; i++)
if(players[i].player)
NetServer::SendPacketToPlayer(players[i].player, STOC_HS_PLAYER_ENTER, scpe);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_ENTER, scpe);
players[scpe.pos] = duelist(dp);
dp->type = scpe.pos;
sctc.type |= scpe.pos;
} else {
observers.insert(dp);
dp->type = NETPLAYER_TYPE_OBSERVER;
sctc.type |= NETPLAYER_TYPE_OBSERVER;
STOC_HS_WatchChange scwc;
scwc.watch_count = observers.size();
for (int i = 0; i < 6; i++)
if (players[i].player)
NetServer::SendPacketToPlayer(players[i].player, STOC_HS_WATCH_CHANGE, scwc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc);
}
NetServer::SendPacketToPlayer(dp, STOC_JOIN_GAME, scjg);
NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc);
for (int i = 0; i < 6; i++)
if (players[i].player) {
STOC_HS_PlayerEnter scpe;
BufferIO::CopyWStr(players[i].player->name, scpe.name, 20);
scpe.pos = i;
NetServer::SendPacketToPlayer(dp, STOC_HS_PLAYER_ENTER, scpe);
if(players[i].ready) {
STOC_HS_PlayerChange scpc;
scpc.status = (i << 4) | PLAYERCHANGE_READY;
NetServer::SendPacketToPlayer(dp, STOC_HS_PLAYER_CHANGE, scpc);
}
}
if(observers.size()) {
STOC_HS_WatchChange scwc;
scwc.watch_count = observers.size();
NetServer::SendPacketToPlayer(dp, STOC_HS_WATCH_CHANGE, scwc);
}
}
void RelayDuel::LeaveGame(DuelPlayer* dp) {
if(dp == host_player) {
EndDuel();
NetServer::StopServer();
} else if(dp->type == NETPLAYER_TYPE_OBSERVER) {
observers.erase(dp);
if(!game_started) {
STOC_HS_WatchChange scwc;
scwc.watch_count = observers.size();
for (int i = 0; i < 6; i++)
if (players[i].player)
NetServer::SendPacketToPlayer(players[i].player, STOC_HS_WATCH_CHANGE, scwc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc);
}
NetServer::DisconnectPlayer(dp);
} else {
if(!game_started) {
STOC_HS_PlayerChange scpc;
players[dp->type] = duelist();
scpc.status = (dp->type << 4) | PLAYERCHANGE_LEAVE;
for (int i = 0; i < 6; i++)
if (players[i].player)
NetServer::SendPacketToPlayer(players[i].player, STOC_HS_PLAYER_CHANGE, scpc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc);
NetServer::DisconnectPlayer(dp);
} else {
EndDuel();
DuelEndProc();
}
}
}
void RelayDuel::ToDuelist(DuelPlayer* dp) {
if(players[0].player && players[1].player && players[2].player
&& players[3].player && players[4].player && players[5].player)
return;
if(dp->type == NETPLAYER_TYPE_OBSERVER) {
observers.erase(dp);
STOC_HS_PlayerEnter scpe;
BufferIO::CopyWStr(dp->name, scpe.name, 20);
for (int i = 0; i < 6; i++)
if (!players[i].player)
dp->type = i;
players[dp->type] = duelist(dp);
scpe.pos = dp->type;
STOC_HS_WatchChange scwc;
scwc.watch_count = observers.size();
for (int i = 0; i < 6; i++)
if (players[i].player) {
NetServer::SendPacketToPlayer(players[i].player, STOC_HS_PLAYER_ENTER, scpe);
NetServer::SendPacketToPlayer(players[i].player, STOC_HS_WATCH_CHANGE, scwc);
}
for(auto pit = observers.begin(); pit != observers.end(); ++pit) {
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_ENTER, scpe);
NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc);
}
STOC_TypeChange sctc;
sctc.type = (dp == host_player ? 0x10 : 0) | dp->type;
NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc);
} else {
if(players[dp->type].ready)
return;
uint8 dptype = (dp->type + 1) % 6;
while(players[dptype].player)
dptype = (dptype + 1) % 6;
STOC_HS_PlayerChange scpc;
scpc.status = (dp->type << 4) | dptype;
for (int i = 0; i < 6; i++)
if (players[i].player)
NetServer::SendPacketToPlayer(players[i].player, STOC_HS_PLAYER_CHANGE, scpc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc);
STOC_TypeChange sctc;
sctc.type = (dp == host_player ? 0x10 : 0) | dptype;
NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc);
players[dptype] = duelist(dp);
players[dp->type] = duelist();
dp->type = dptype;
}
}
void RelayDuel::ToObserver(DuelPlayer* dp) {
if(dp->type > 5)
return;
STOC_HS_PlayerChange scpc;
scpc.status = (dp->type << 4) | PLAYERCHANGE_OBSERVE;
for (int i = 0; i < 6; i++)
if (players[i].player)
NetServer::SendPacketToPlayer(players[i].player, STOC_HS_PLAYER_CHANGE, scpc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc);
players[dp->type] = duelist();
dp->type = NETPLAYER_TYPE_OBSERVER;
observers.insert(dp);
STOC_TypeChange sctc;
sctc.type = (dp == host_player ? 0x10 : 0) | dp->type;
NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc);
}
void RelayDuel::PlayerReady(DuelPlayer* dp, bool is_ready) {
if(dp->type > 5 || players[dp->type].ready == is_ready)
return;
if(is_ready) {
unsigned int deckerror = 0;
if(!host_info.no_check_deck) {
if(players[dp->type].deck_error) {
deckerror = (DECKERROR_UNKNOWNCARD << 28) + players[dp->type].deck_error;
} else {
bool allow_ocg = host_info.rule == 0 || host_info.rule == 2;
bool allow_tcg = host_info.rule == 1 || host_info.rule == 2;
deckerror = deckManager.CheckDeck(players[dp->type].pdeck, host_info.lflist, allow_ocg, allow_tcg, host_info.doubled, host_info.forbiddentypes);
}
}
if(deckerror) {
STOC_HS_PlayerChange scpc;
scpc.status = (dp->type << 4) | PLAYERCHANGE_NOTREADY;
NetServer::SendPacketToPlayer(dp, STOC_HS_PLAYER_CHANGE, scpc);
STOC_ErrorMsg scem;
scem.msg = ERRMSG_DECKERROR;
scem.code = deckerror;
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
return;
}
}
players[dp->type].ready = is_ready;
STOC_HS_PlayerChange scpc;
scpc.status = (dp->type << 4) | (is_ready ? PLAYERCHANGE_READY : PLAYERCHANGE_NOTREADY);
for (int i = 0; i < 6; i++)
if (players[i].player)
NetServer::SendPacketToPlayer(players[i].player, STOC_HS_PLAYER_CHANGE, scpc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc);
}
void RelayDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) {
if(pos > 5 || dp != host_player || dp == players[pos].player || !players[pos].player)
return;
LeaveGame(players[pos].player);
}
void RelayDuel::UpdateDeck(DuelPlayer* dp, void* pdata) {
if(dp->type > 5 || players[dp->type].ready)
return;
char* deckbuf = (char*)pdata;
int mainc = BufferIO::ReadInt32(deckbuf);
int sidec = BufferIO::ReadInt32(deckbuf);
players[dp->type].deck_error = deckManager.LoadDeck(players[dp->type].pdeck, (int*)deckbuf, mainc, sidec, 0, 0, host_info.doubled);
}
void RelayDuel::StartDuel(DuelPlayer* dp) {
if(dp != host_player)
return;
for (int i = 0; i < 6; i++)
if (players[i].player && !players[i].ready)
return;
if(!((players[0].ready || players[1].ready || players[2].ready) &&
(players[3].ready || players[4].ready || players[5].ready)))
return;
NetServer::StopListen();
game_started = true;
//NetServer::StopBroadcast();
for (int i = 0; i < 6; ++i)
if (players[i].player)
NetServer::SendPacketToPlayer(players[i].player, STOC_DUEL_START);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) {
(*oit)->state = CTOS_LEAVE_GAME;
NetServer::ReSendToPlayer(*oit);
}
for (startp[0] = 0; startp[0] < 3; startp[0]++)
if (players[startp[0]].player)
break;
for (startp[1] = 3; startp[1] < 5; startp[1]++)
if (players[startp[1]].player)
break;
NetServer::SendPacketToPlayer(players[startp[0]].player, STOC_SELECT_HAND);
NetServer::ReSendToPlayer(players[startp[1]].player);
hand_result[0] = 0;
hand_result[1] = 0;
players[startp[0]].player->state = CTOS_HAND_RESULT;
players[startp[1]].player->state = CTOS_HAND_RESULT;
}
void RelayDuel::HandResult(DuelPlayer* dp, unsigned char res) {
if(res > 3 || dp->state != CTOS_HAND_RESULT)
return;
if(dp->type == 0)
hand_result[0] = res;
else
hand_result[1] = res;
if(hand_result[0] && hand_result[1]) {
STOC_HandResult schr;
schr.res1 = hand_result[0];
schr.res2 = hand_result[1];
for (int i = 0; i < 3; i++)
if(players[i].player)
NetServer::SendPacketToPlayer(players[i].player, STOC_HAND_RESULT, schr);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
schr.res1 = hand_result[1];
schr.res2 = hand_result[0];
for (int i = 3; i < 6; i++)
if (players[i].player)
NetServer::SendPacketToPlayer(players[i].player, STOC_HAND_RESULT, schr);
if(hand_result[0] == hand_result[1]) {
NetServer::SendPacketToPlayer(players[startp[0]].player, STOC_SELECT_HAND);
NetServer::ReSendToPlayer(players[startp[1]].player);
hand_result[0] = 0;
hand_result[1] = 0;
players[startp[0]].player->state = CTOS_HAND_RESULT;
players[startp[1]].player->state = CTOS_HAND_RESULT;
} else if((hand_result[0] == 1 && hand_result[1] == 2)
|| (hand_result[0] == 2 && hand_result[1] == 3)
|| (hand_result[0] == 3 && hand_result[1] == 1)) {
NetServer::SendPacketToPlayer(players[startp[1]].player, CTOS_TP_RESULT);
players[startp[0]].player->state = 0xff;
players[startp[1]].player->state = CTOS_TP_RESULT;
} else {
NetServer::SendPacketToPlayer(players[startp[0]].player, CTOS_TP_RESULT);
players[startp[1]].player->state = 0xff;
players[startp[0]].player->state = CTOS_TP_RESULT;
}
}
}
void RelayDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
if(dp->state != CTOS_TP_RESULT)
return;
bool swapped = false;
mtrandom rnd;
if((tp && dp->type == startp[1]) || (!tp && dp->type == startp[0])) {
std::swap(players[0], players[3]);
std::swap(players[1], players[4]);
std::swap(players[2], players[5]);
for (int i = 0; i < 6; i++)
if(players[i].player)
players[i].player->type = i;
swapped = true;
int starttmp0 = startp[1] - 3;
int starttmp1 = startp[0] + 3;
startp[0] = starttmp0;
startp[1] = starttmp1;
}
turn_count = 0;
cur_player[0] = players[startp[0]].player;
cur_player[1] = players[startp[1]].player;
dp->state = CTOS_RESPONSE;
ReplayHeader rh;
rh.id = 0x31707279;
rh.version = PRO_VERSION;
rh.flag = REPLAY_TAG + REPLAY_LUA64;
time_t seed = time(0);
rh.seed = seed;
last_replay.BeginRecord(false);
last_replay.WriteHeader(rh);
rnd.reset(seed);
//records the replay with the new system
new_replay.BeginRecord();
rh.id = 0x58707279;
rh.flag |= REPLAY_NEWREPLAY;
new_replay.WriteHeader(rh);
for (int i = 0; i < 6; i++)
if (players[i].player->name) {
last_replay.WriteData(players[i].player->name, 40, false);
new_replay.WriteData(players[i].player->name, 40, false);
}
replay_stream.clear();
if(!host_info.no_shuffle_deck) {
for(int p = 0; p < 6; p++)
if (players[p].player)
for(size_t i = players[p].pdeck.main.size() - 1; i > 0; --i) {
int swap = rnd.real() * (i + 1);
std::swap(players[p].pdeck.main[i], players[p].pdeck.main[swap]);
}
}
time_limit[0] = host_info.time_limit;
time_limit[1] = host_info.time_limit;
set_script_reader(default_script_reader);
set_card_reader((card_reader)DataManager::CardReader);
set_message_handler((message_handler)RelayDuel::MessageHandler);
rnd.reset(seed);
pduel = create_duel(rnd.rand());
set_player_info(pduel, 0, host_info.start_lp, host_info.start_hand, host_info.draw_count);
set_player_info(pduel, 1, host_info.start_lp, host_info.start_hand, host_info.draw_count);
int opt = host_info.duel_flag;
if(host_info.no_shuffle_deck)
opt |= DUEL_PSEUDO_SHUFFLE;
if(host_info.speed)
opt |= SPEED_DUEL;
opt |= DUEL_RELAY_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_hand, false);
last_replay.WriteInt32(host_info.draw_count, false);
last_replay.WriteInt32(opt, false);
last_replay.Flush();
//
last_replay.WriteInt32(players[startp[0]].pdeck.main.size() + host_info.rule_count, false);
for(int32 i = (int32)players[startp[0]].pdeck.main.size() - 1; i >= 0; --i) {
new_card(pduel, players[startp[0]].pdeck.main[i]->first, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(players[startp[0]].pdeck.main[i]->first, false);
}
if(host_info.sealed) {
new_card(pduel, 511005092, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(511005092, false);
}
if(host_info.booster) {
new_card(pduel, 511005093, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(511005093, false);
}
if(host_info.concentration) {
new_card(pduel, 511004322, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(511004322, false);
}
if(host_info.boss) {
new_card(pduel, 95000000, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(95000000, false);
}
if(host_info.city) {
new_card(pduel, 511004014, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(511004014, false);
}
if(host_info.kingdom) {
new_card(pduel, 511002621, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(511002621, false);
}
if(host_info.dimension) {
new_card(pduel, 511600002, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(511600002, false);
}
if(host_info.turbo1) {
new_card(pduel, 511002094, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(511002094, false);
}
if(host_info.turbo2) {
new_card(pduel, 110000000, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(110000000, false);
}
if(host_info.command) {
new_card(pduel, 95200000, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(95200000, false);
}
if(host_info.master) {
new_card(pduel, 300, 0, 0, 0, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(300, false);
}
if(host_info.destiny_draw) {
new_card(pduel, 511004000, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(511004000, false);
}
last_replay.WriteInt32(players[startp[0]].pdeck.extra.size(), false);
for(int32 i = (int32)players[startp[0]].pdeck.extra.size() - 1; i >= 0; --i) {
new_card(pduel, players[startp[0]].pdeck.extra[i]->first, 0, 0, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(players[startp[0]].pdeck.extra[i]->first, false);
}
//
for(int p = startp[0] + 1, num = 1; p < 3; p++)
if(players[p].player) {
last_replay.WriteInt32(players[p].pdeck.main.size(), false);
for (int32 i = (int32)players[p].pdeck.main.size() - 1; i >= 0; --i) {
new_relay_card(pduel, players[p].pdeck.main[i]->first, 0, LOCATION_DECK, num);
last_replay.WriteInt32(players[p].pdeck.main[i]->first, false);
}
last_replay.WriteInt32(players[p].pdeck.extra.size(), false);
for (int32 i = (int32)players[p].pdeck.extra.size() - 1; i >= 0; --i) {
new_relay_card(pduel, players[p].pdeck.extra[i]->first, 0, LOCATION_EXTRA, num);
last_replay.WriteInt32(players[p].pdeck.extra[i]->first, false);
}
num++;
}
//
last_replay.WriteInt32(players[startp[1]].pdeck.main.size(), false);
for(int32 i = (int32)players[startp[1]].pdeck.main.size() - 1; i >= 0; --i) {
new_card(pduel, players[startp[1]].pdeck.main[i]->first, 1, 1, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(players[startp[1]].pdeck.main[i]->first, false);
}
last_replay.WriteInt32(players[startp[1]].pdeck.extra.size(), false);
for(int32 i = (int32)players[startp[1]].pdeck.extra.size() - 1; i >= 0; --i) {
new_card(pduel, players[startp[1]].pdeck.extra[i]->first, 1, 1, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
last_replay.WriteInt32(players[startp[1]].pdeck.extra[i]->first, false);
}
//
for(int p = startp[1] + 1, num = 1; p < 6; p++)
if(players[p].player) {
last_replay.WriteInt32(players[p].pdeck.main.size(), false);
for (int32 i = (int32)players[p].pdeck.main.size() - 1; i >= 0; --i) {
new_relay_card(pduel, players[p].pdeck.main[i]->first, 1, LOCATION_DECK, num);
last_replay.WriteInt32(players[p].pdeck.main[i]->first, false);
}
last_replay.WriteInt32(players[p].pdeck.extra.size(), false);
for (int32 i = (int32)players[p].pdeck.extra.size() - 1; i >= 0; --i) {
new_relay_card(pduel, players[p].pdeck.extra[i]->first, 1, LOCATION_EXTRA, num);
last_replay.WriteInt32(players[p].pdeck.extra[i]->first, false);
}
num++;
}
last_replay.Flush();
char startbuf[32], *pbuf = startbuf;
BufferIO::WriteInt8(pbuf, MSG_START);
BufferIO::WriteInt8(pbuf, 0);
BufferIO::WriteInt32(pbuf, host_info.start_lp);
BufferIO::WriteInt32(pbuf, host_info.start_lp);
BufferIO::WriteInt16(pbuf, query_field_count(pduel, 0, 0x1));
BufferIO::WriteInt16(pbuf, query_field_count(pduel, 0, 0x40));
BufferIO::WriteInt16(pbuf, query_field_count(pduel, 1, 0x1));
BufferIO::WriteInt16(pbuf, query_field_count(pduel, 1, 0x40));
for (int i = 0; i < 3; i++)
if (players[i].player)
NetServer::SendBufferToPlayer(players[i].player, STOC_GAME_MSG, startbuf, 18);
startbuf[1] = 1;
for (int i = 3; i < 6; i++)
if (players[i].player)
NetServer::SendBufferToPlayer(players[i].player, STOC_GAME_MSG, startbuf, 18);
if(!swapped)
startbuf[1] = 0x10;
else startbuf[1] = 0x11;
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
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(1);
new_replay.WriteStream(replay_stream);
start_duel(pduel, opt);
Process();
}
void RelayDuel::Process() {
char engineBuffer[0x1000];
unsigned int engFlag = 0, engLen = 0;
int stop = 0;
while (!stop) {
if (engFlag == 2)
break;
int result = process(pduel);
engLen = result & 0xffff;
engFlag = result >> 16;
if (engLen > 0) {
get_message(pduel, (byte*)&engineBuffer);
stop = Analyze(engineBuffer, engLen);
}
}
if(stop == 2)
DuelEndProc();
}
void RelayDuel::DuelEndProc() {
NetServer::SendPacketToPlayer(players[startp[0]].player, STOC_DUEL_END);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
NetServer::StopServer();
}
void RelayDuel::Surrender(DuelPlayer* dp) {
return;
}
int RelayDuel::Analyze(char* msgbuffer, unsigned int len) {
char* offset, *pbufw, *pbuf = msgbuffer;
int player, count, type;
while (pbuf - msgbuffer < (int)len) {
replay_stream.clear();
bool record = true;
ReplayPacket pk;
offset = pbuf;
unsigned char engType = BufferIO::ReadUInt8(pbuf);
pk.message = engType;
pk.length = len - 1;
memcpy(pk.data, pbuf, pk.length);
switch (engType) {
case MSG_RETRY: {
WaitforResponse(last_response);
NetServer::SendBufferToPlayer(cur_player[last_response], STOC_GAME_MSG, offset, pbuf - offset);
replay_stream.push_back(pk);
return 1;
}
case MSG_HINT: {
type = BufferIO::ReadInt8(pbuf);
player = BufferIO::ReadInt8(pbuf);
BufferIO::ReadInt64(pbuf);
switch (type) {
case 1:
case 2:
case 3:
case 5:
case 10: {
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
record = false;
break;
}
case 4:
case 6:
case 7:
case 8:
case 9: {
for(int i = 0; i < 6; ++i)
if(players[i].player != cur_player[player])
NetServer::SendBufferToPlayer(players[i].player, STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
}
break;
}
case MSG_WIN: {
player = BufferIO::ReadInt8(pbuf);
type = BufferIO::ReadInt8(pbuf);
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
replay_stream.push_back(pk);
EndDuel();
return 2;
}
case MSG_SELECT_BATTLECMD: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 15;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8 + 2;
RefreshMzone(0);
RefreshMzone(1);
RefreshSzone(0);
RefreshSzone(1);
RefreshHand(0);
RefreshHand(1);
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
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 * 15 + 3;
RefreshMzone(0);
RefreshMzone(1);
RefreshSzone(0);
RefreshSzone(1);
RefreshHand(0);
RefreshHand(1);
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_SELECT_EFFECTYN: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 16;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_SELECT_YESNO: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 8;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_SELECT_OPTION: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_SELECT_CARD:
case MSG_SELECT_TRIBUTE: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 3;
count = BufferIO::ReadInt8(pbuf);
int c/*, l, s, ss, code*/;
for (int i = 0; i < count; ++i) {
pbufw = pbuf;
/*code = */BufferIO::ReadInt32(pbuf);
c = BufferIO::ReadInt8(pbuf);
/*l = */BufferIO::ReadInt8(pbuf);
/*s = */BufferIO::ReadInt8(pbuf);
/*ss = */BufferIO::ReadInt8(pbuf);
if (c != player) BufferIO::WriteInt32(pbufw, 0);
}
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_SELECT_UNSELECT_CARD: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 4;
count = BufferIO::ReadInt8(pbuf);
int c/*, l, s, ss, code*/;
for (int i = 0; i < count; ++i) {
pbufw = pbuf;
/*code = */BufferIO::ReadInt32(pbuf);
c = BufferIO::ReadInt8(pbuf);
/*l = */BufferIO::ReadInt8(pbuf);
/*s = */BufferIO::ReadInt8(pbuf);
/*ss = */BufferIO::ReadInt8(pbuf);
if (c != player) BufferIO::WriteInt32(pbufw, 0);
}
count = BufferIO::ReadInt8(pbuf);
for (int i = 0; i < count; ++i) {
pbufw = pbuf;
/*code = */BufferIO::ReadInt32(pbuf);
c = BufferIO::ReadInt8(pbuf);
/*l = */BufferIO::ReadInt8(pbuf);
/*s = */BufferIO::ReadInt8(pbuf);
/*ss = */BufferIO::ReadInt8(pbuf);
if (c != player) BufferIO::WriteInt32(pbufw, 0);
}
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_SELECT_CHAIN: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += 10 + count * 17;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_SELECT_PLACE:
case MSG_SELECT_DISFIELD: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_SELECT_POSITION: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_SELECT_COUNTER: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 4;
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 9;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
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;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_SORT_CARD:
case MSG_SORT_CHAIN: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_CONFIRM_DECKTOP: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_CONFIRM_EXTRATOP: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 7;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for (auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_CONFIRM_CARDS: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
if(pbuf[5] != LOCATION_DECK) {
pbuf += count * 7;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
} else {
pbuf += count * 7;
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
}
break;
}
case MSG_SHUFFLE_DECK: {
player = BufferIO::ReadInt8(pbuf);
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
PseudoRefreshDeck(player);
break;
}
case MSG_SHUFFLE_HAND: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
for (int p = player * 3, i = 0; i < 3; i++, p++)
if(players[p].player)
NetServer::SendBufferToPlayer(players[p].player, STOC_GAME_MSG, offset, (pbuf - offset) + count * 4);
for(int i = 0; i < count; ++i)
BufferIO::WriteInt32(pbuf, 0);
for (int p = (1 - player) * 3, i = 0; i < 3; i++, p++)
if(players[p].player)
NetServer::SendBufferToPlayer(players[p].player, STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshHand(player, 0x781fff, 0);
break;
}
case MSG_SHUFFLE_EXTRA: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
for (int p = player * 3, i = 0; i < 3; i++, p++)
if(players[p].player)
NetServer::SendBufferToPlayer(players[p].player, STOC_GAME_MSG, offset, (pbuf - offset) + count * 4);
for(int i = 0; i < count; ++i)
BufferIO::WriteInt32(pbuf, 0);
for (int p = (1 - player) * 3, i = 0; i < 3; i++, p++)
if(players[p].player)
NetServer::SendBufferToPlayer(players[p].player, STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshExtra(player);
break;
}
case MSG_REFRESH_DECK: {
pbuf++;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_SWAP_GRAVE_DECK: {
player = BufferIO::ReadInt8(pbuf);
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshGrave(player);
break;
}
case MSG_REVERSE_DECK: {
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
PseudoRefreshDeck(0);
PseudoRefreshDeck(1);
break;
}
case MSG_DECK_TOP: {
pbuf += 6;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_SHUFFLE_SET_CARD: {
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 8;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshMzone(0, 0x181fff, 0);
RefreshMzone(1, 0x181fff, 0);
break;
}
case MSG_NEW_TURN: {
pbuf++;
time_limit[0] = host_info.time_limit;
time_limit[1] = host_info.time_limit;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
turn_count++;
break;
}
case MSG_NEW_PHASE: {
pbuf += 2;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshMzone(0);
RefreshMzone(1);
RefreshSzone(0);
RefreshSzone(1);
RefreshHand(0);
RefreshHand(1);
break;
}
case MSG_MOVE: {
pbufw = pbuf;
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;
for (int p = cc * 3, i = 0; i < 3; i++, p++)
if (players[p].player)
NetServer::SendBufferToPlayer(players[p].player, STOC_GAME_MSG, offset, pbuf - offset);
if (!(cl & (LOCATION_GRAVE + LOCATION_OVERLAY)) && ((cl & (LOCATION_DECK + LOCATION_HAND)) || (cp & POS_FACEDOWN)))
BufferIO::WriteInt32(pbufw, 0);
for (int p = (1 - cc) * 3, i = 0; i < 3; i++, p++)
if (players[p].player)
NetServer::SendBufferToPlayer(players[p].player, STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
if (cl != 0 && (cl & 0x80) == 0 && (cl != pl || pc != cc))
RefreshSingle(cc, cl, cs);
break;
}
case MSG_POS_CHANGE: {
int cc = pbuf[4];
int cl = pbuf[5];
int cs = pbuf[6];
int pp = pbuf[7];
int cp = pbuf[8];
pbuf += 9;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
if((pp & POS_FACEDOWN) && (cp & POS_FACEUP))
RefreshSingle(cc, cl, cs);
break;
}
case MSG_SET: {
BufferIO::WriteInt32(pbuf, 0);
pbuf += 4;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_SWAP: {
int c1 = pbuf[4];
int l1 = pbuf[5];
int s1 = pbuf[6];
int c2 = pbuf[12];
int l2 = pbuf[13];
int s2 = pbuf[14];
pbuf += 16;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshSingle(c1, l1, s1);
RefreshSingle(c2, l2, s2);
break;
}
case MSG_FIELD_DISABLED: {
pbuf += 4;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_SUMMONING: {
pbuf += 8;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_SUMMONED: {
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshMzone(0);
RefreshMzone(1);
RefreshSzone(0);
RefreshSzone(1);
break;
}
case MSG_SPSUMMONING: {
pbuf += 8;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_SPSUMMONED: {
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshMzone(0);
RefreshMzone(1);
RefreshSzone(0);
RefreshSzone(1);
break;
}
case MSG_FLIPSUMMONING: {
RefreshSingle(pbuf[4], pbuf[5], pbuf[6]);
pbuf += 8;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_FLIPSUMMONED: {
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshMzone(0);
RefreshMzone(1);
RefreshSzone(0);
RefreshSzone(1);
break;
}
case MSG_CHAINING: {
pbuf += 20;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_CHAINED: {
pbuf++;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshMzone(0);
RefreshMzone(1);
RefreshSzone(0);
RefreshSzone(1);
RefreshHand(0);
RefreshHand(1);
break;
}
case MSG_CHAIN_SOLVING: {
pbuf++;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_CHAIN_SOLVED: {
pbuf++;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshMzone(0);
RefreshMzone(1);
RefreshSzone(0);
RefreshSzone(1);
RefreshHand(0);
RefreshHand(1);
break;
}
case MSG_CHAIN_END: {
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshMzone(0);
RefreshMzone(1);
RefreshSzone(0);
RefreshSzone(1);
RefreshHand(0);
RefreshHand(1);
break;
}
case MSG_CHAIN_NEGATED: {
pbuf++;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_CHAIN_DISABLED: {
pbuf++;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_CARD_SELECTED: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
break;
}
case MSG_RANDOM_SELECTED: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_BECOME_TARGET: {
count = BufferIO::ReadInt8(pbuf);
pbuf += count * 4;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_DRAW: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbufw = pbuf;
pbuf += count * 4;
for (int p = player * 3, i = 0; i < 3; i++, p++)
if(players[p].player)
NetServer::SendBufferToPlayer(players[p].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = 0; i < count; ++i) {
if(!(pbufw[3] & 0x80))
BufferIO::WriteInt32(pbufw, 0);
else
pbufw += 4;
}
for (int p = (1 - player) * 3, i = 0; i < 3; i++, p++)
if(players[p].player)
NetServer::SendBufferToPlayer(players[p].player, STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_DAMAGE: {
pbuf += 5;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_RECOVER: {
pbuf += 5;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_EQUIP: {
pbuf += 8;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_LPUPDATE: {
pbuf += 5;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_UNEQUIP: {
pbuf += 4;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_CARD_TARGET: {
pbuf += 8;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_CANCEL_TARGET: {
pbuf += 8;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_PAY_LPCOST: {
pbuf += 5;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_ADD_COUNTER: {
pbuf += 7;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_REMOVE_COUNTER: {
pbuf += 7;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_ATTACK: {
pbuf += 8;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_BATTLE: {
pbuf += 26;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_ATTACK_DISABLED: {
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_DAMAGE_STEP_START: {
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshMzone(0);
RefreshMzone(1);
break;
}
case MSG_DAMAGE_STEP_END: {
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
RefreshMzone(0);
RefreshMzone(1);
break;
}
case MSG_MISSED_EFFECT: {
player = pbuf[0];
pbuf += 8;
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
break;
}
case MSG_TOSS_COIN: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_TOSS_DICE: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += count;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_ROCK_PAPER_SCISSORS: {
player = BufferIO::ReadInt8(pbuf);
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_HAND_RES: {
pbuf += 1;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for (auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_ANNOUNCE_RACE: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_ANNOUNCE_ATTRIB: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 5;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_ANNOUNCE_CARD: {
player = BufferIO::ReadInt8(pbuf);
pbuf += 4;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_ANNOUNCE_NUMBER:
case MSG_ANNOUNCE_CARD_FILTER: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
pbuf += 8 * count;
WaitforResponse(player);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
return 1;
}
case MSG_CARD_HINT: {
pbuf += 13;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_PLAYER_HINT: {
pbuf += 10;
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
break;
}
case MSG_TAG_SWAP: {
pbufw = pbuf;
player = BufferIO::ReadInt8(pbuf);
int newp = 0;
for (int i = startp[player]; i < (player == 0) ? 3 : 6; i++)
if (players[i].player == cur_player[player]) {
for (newp = i + 1; newp < (player == 0) ? 3 : 6; newp++)
if (players[newp].player)
break;
break;
}
BufferIO::WriteInt8(pbufw, player + (newp << 4));
/*int mcount = */BufferIO::ReadInt8(pbuf);
int ecount = BufferIO::ReadInt8(pbuf);
/*int pcount = */BufferIO::ReadInt8(pbuf);
int hcount = BufferIO::ReadInt8(pbuf);
pbufw += 4;
pbuf += hcount * 4 + ecount * 4 + 4;
for (int p = player * 3, i = 0; i < 3; i++, p++)
if (players[p].player)
NetServer::SendBufferToPlayer(players[p].player, STOC_GAME_MSG, offset, pbuf - offset);
for (int i = 0; i < hcount; ++i) {
if(!(pbufw[3] & 0x80))
BufferIO::WriteInt32(pbufw, 0);
else
pbufw += 4;
}
for (int i = 0; i < ecount; ++i) {
if(!(pbufw[3] & 0x80))
BufferIO::WriteInt32(pbufw, 0);
else
pbufw += 4;
}
for (int p = (1 - player) * 3, i = 0; i < 3; i++, p++)
if(players[p].player)
NetServer::SendBufferToPlayer(players[p].player, STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
for (int i = startp[player]; i < (player == 0) ? 3 : 6; i++)
if (players[i].player == cur_player[player]) {
for (int j = i + 1; j < (player == 0) ? 3 : 6; j++)
if (players[j].player) {
cur_player[player] = players[j].player;
break;
}
break;
}
cur_player[player] = players[newp].player;
PseudoRefreshDeck(player);
RefreshExtra(player);
RefreshMzone(0, 0x81fff, 0);
RefreshMzone(1, 0x81fff, 0);
RefreshSzone(0, 0x681fff, 0);
RefreshSzone(1, 0x681fff, 0);
RefreshHand(0, 0x781fff, 0);
RefreshHand(1, 0x781fff, 0);
break;
}
case MSG_MATCH_KILL: {
pbuf += 4;
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
pk.length = (pbuf - offset) - 1;
if (record)
replay_stream.insert(replay_stream.begin(), pk);
new_replay.WriteStream(replay_stream);
}
return 0;
}
void RelayDuel::GetResponse(DuelPlayer* dp, void* pdata, unsigned int len) {
byte resb[64];
memcpy(resb, pdata, len);
last_replay.WriteInt8(len);
last_replay.WriteData(resb, len);
set_responseb(pduel, resb);
players[dp->type].player->state = 0xff;
if(host_info.time_limit) {
int resp_type = dp->type < 2 ? 0 : 1;
if(time_limit[resp_type] >= time_elapsed)
time_limit[resp_type] -= time_elapsed;
else time_limit[resp_type] = 0;
event_del(etimer);
}
Process();
}
void RelayDuel::EndDuel() {
if(!pduel)
return;
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);
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[startp[0]].player, STOC_NEW_REPLAY, nreplaybuf, sizeof(ReplayHeader) + new_replay.comp_size);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for (auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
end_duel(pduel);
pduel = 0;
}
void RelayDuel::WaitforResponse(int playerid) {
last_response = playerid;
unsigned char msg = MSG_WAITING;
for(int i = 0; i < 6; ++i)
if(players[i].player && players[i].player != cur_player[playerid])
NetServer::SendPacketToPlayer(players[i].player, STOC_GAME_MSG, msg);
if(host_info.time_limit) {
STOC_TimeLimit sctl;
sctl.player = playerid;
sctl.left_time = time_limit[playerid];
NetServer::SendPacketToPlayer(players[startp[0]].player, STOC_TIME_LIMIT, sctl);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
cur_player[playerid]->state = CTOS_TIME_CONFIRM;
} else
cur_player[playerid]->state = CTOS_RESPONSE;
}
void RelayDuel::TimeConfirm(DuelPlayer* dp) {
if(host_info.time_limit == 0)
return;
if(dp != cur_player[last_response])
return;
cur_player[last_response]->state = CTOS_RESPONSE;
time_elapsed = 0;
timeval timeout = {1, 0};
event_add(etimer, &timeout);
}
void RelayDuel::RefreshMzone(int player, int flag, int use_cache) {
char query_buffer[0x2000];
char* qbuf = query_buffer;
BufferIO::WriteInt8(qbuf, MSG_UPDATE_DATA);
BufferIO::WriteInt8(qbuf, player);
BufferIO::WriteInt8(qbuf, LOCATION_MZONE);
int len = query_field_card(pduel, player, LOCATION_MZONE, flag, (unsigned char*)qbuf, use_cache);
int pid = startp[player];
NetServer::SendBufferToPlayer(players[pid].player, STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
for (int i = pid + 1; i < player * 3 + 3; i++)
if(players[i].player)
NetServer::ReSendToPlayer(players[i].player);
int qlen = 0;
while(qlen < len) {
int clen = BufferIO::ReadInt32(qbuf);
qlen += clen;
if (clen == 4)
continue;
if (qbuf[11] & POS_FACEDOWN)
memset(qbuf, 0, clen - 4);
qbuf += clen - 4;
}
pid = startp[1 - player];
NetServer::SendBufferToPlayer(players[pid].player, STOC_GAME_MSG, query_buffer, len + 3);
for (int i = pid + 1; i < (1 - player) * 3 + 3; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
}
void RelayDuel::RefreshSzone(int player, int flag, int use_cache) {
char query_buffer[0x2000];
char* qbuf = query_buffer;
BufferIO::WriteInt8(qbuf, MSG_UPDATE_DATA);
BufferIO::WriteInt8(qbuf, player);
BufferIO::WriteInt8(qbuf, LOCATION_SZONE);
int len = query_field_card(pduel, player, LOCATION_SZONE, flag, (unsigned char*)qbuf, use_cache);
int pid = startp[player];
NetServer::SendBufferToPlayer(players[pid].player, STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
for (int i = pid + 1; i < player * 3 + 3; i++)
if(players[i].player)
NetServer::ReSendToPlayer(players[i].player);
int qlen = 0;
while(qlen < len) {
int clen = BufferIO::ReadInt32(qbuf);
qlen += clen;
if (clen == 4)
continue;
if (qbuf[11] & POS_FACEDOWN)
memset(qbuf, 0, clen - 4);
qbuf += clen - 4;
}
pid = startp[1 - player];
NetServer::SendBufferToPlayer(players[pid].player, STOC_GAME_MSG, query_buffer, len + 3);
for (int i = pid + 1; i < (1 - player) * 3 + 3; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
}
void RelayDuel::RefreshHand(int player, int flag, int use_cache) {
char query_buffer[0x2000];
char* qbuf = query_buffer;
BufferIO::WriteInt8(qbuf, MSG_UPDATE_DATA);
BufferIO::WriteInt8(qbuf, player);
BufferIO::WriteInt8(qbuf, LOCATION_HAND);
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);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
int qlen = 0;
while(qlen < len) {
int slen = BufferIO::ReadInt32(qbuf);
int qflag = *(int*)qbuf;
int pos = slen - 8;
if(qflag & QUERY_LSCALE)
pos -= 4;
if(qflag & QUERY_RSCALE)
pos -= 4;
if(!qbuf[pos])
memset(qbuf, 0, slen - 4);
qbuf += slen - 4;
qlen += slen;
}
for(int i = 0; i < 6; ++i)
if(players[i].player && players[i].player != cur_player[player])
NetServer::SendBufferToPlayer(players[i].player, STOC_GAME_MSG, query_buffer, len + 3);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
}
void RelayDuel::RefreshGrave(int player, int flag, int use_cache) {
char query_buffer[0x2000];
char* qbuf = query_buffer;
BufferIO::WriteInt8(qbuf, MSG_UPDATE_DATA);
BufferIO::WriteInt8(qbuf, player);
BufferIO::WriteInt8(qbuf, LOCATION_GRAVE);
int len = query_field_card(pduel, player, LOCATION_GRAVE, flag, (unsigned char*)qbuf, use_cache);
NetServer::SendBufferToPlayer(players[startp[0]].player, STOC_GAME_MSG, query_buffer, len + 3);
for (int i = startp[0] + 1; i < 6; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
}
void RelayDuel::RefreshExtra(int player, int flag, int use_cache) {
char query_buffer[0x2000];
char* qbuf = query_buffer;
BufferIO::WriteInt8(qbuf, MSG_UPDATE_DATA);
BufferIO::WriteInt8(qbuf, player);
BufferIO::WriteInt8(qbuf, LOCATION_EXTRA);
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);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
}
void RelayDuel::RefreshSingle(int player, int location, int sequence, int flag) {
char query_buffer[0x2000];
char* qbuf = query_buffer;
BufferIO::WriteInt8(qbuf, MSG_UPDATE_CARD);
BufferIO::WriteInt8(qbuf, player);
BufferIO::WriteInt8(qbuf, location);
BufferIO::WriteInt8(qbuf, sequence);
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) {
int pid = startp[player];
NetServer::SendBufferToPlayer(players[pid].player, STOC_GAME_MSG, query_buffer, len + 4);
for (int i = pid + 1; i < player * 3 + 3; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
if(qbuf[15] & POS_FACEUP) {
pid = startp[1 - player];
for (int i = pid; i < (1 - player) * 3 + 3; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
}
} else {
int pid = startp[player];
NetServer::SendBufferToPlayer(players[pid].player, STOC_GAME_MSG, query_buffer, len + 4);
for (int i = pid + 1; i < player * 3 + 3; i++)
if (players[i].player)
NetServer::ReSendToPlayer(players[i].player);
if(location == LOCATION_REMOVED && (qbuf[15] & POS_FACEDOWN))
return;
if (location & 0x90) {
for(int i = 0; i < 6; ++i)
if(players[i].player && players[i].player != cur_player[player])
NetServer::ReSendToPlayer(players[i].player);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
}
}
}
void RelayDuel::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 RelayDuel::MessageHandler(long fduel, int type) {
if(!enable_log)
return 0;
char msgbuf[1024];
get_log_message(fduel, (byte*)msgbuf);
mainGame->AddDebugMsg(msgbuf);
return 0;
}
void RelayDuel::RelayTimer(evutil_socket_t fd, short events, void* arg) {
RelayDuel* sd = static_cast<RelayDuel*>(arg);
sd->time_elapsed++;
if(sd->time_elapsed >= sd->time_limit[sd->last_response]) {
unsigned char wbuf[3];
uint32 player = sd->last_response;
wbuf[0] = MSG_WIN;
wbuf[1] = 1 - player;
wbuf[2] = 0x3;
NetServer::SendBufferToPlayer(sd->players[sd->startp[0]].player, STOC_GAME_MSG, wbuf, 3);
for (int i = sd->startp[0] + 1; i < 6; i++)
if (sd->players[i].player)
NetServer::ReSendToPlayer(sd->players[i].player);
ReplayPacket p((char*)wbuf, 3);
sd->replay_stream.push_back(p);
sd->EndDuel();
sd->DuelEndProc();
event_del(sd->etimer);
}
}
}
#ifndef RELAY_DUEL_H
#define RELAY_DUEL_H
#include "config.h"
#include "network.h"
#include "replay.h"
namespace ygo {
class RelayDuel: public DuelMode {
public:
RelayDuel();
virtual ~RelayDuel();
virtual void Chat(DuelPlayer* dp, void* pdata, int len);
virtual void JoinGame(DuelPlayer* dp, void* pdata, bool is_creater);
virtual void LeaveGame(DuelPlayer* dp);
virtual void ToDuelist(DuelPlayer* dp);
virtual void ToObserver(DuelPlayer* dp);
virtual void PlayerReady(DuelPlayer* dp, bool ready);
virtual void PlayerKick(DuelPlayer* dp, unsigned char pos);
virtual void UpdateDeck(DuelPlayer* dp, void* pdata);
virtual void StartDuel(DuelPlayer* dp);
virtual void HandResult(DuelPlayer* dp, unsigned char res);
virtual void TPResult(DuelPlayer* dp, unsigned char tp);
virtual void Process();
virtual void Surrender(DuelPlayer* dp);
virtual int Analyze(char* msgbuffer, unsigned int len);
virtual void GetResponse(DuelPlayer* dp, void* pdata, unsigned int len);
virtual void TimeConfirm(DuelPlayer* dp);
virtual void EndDuel();
void DuelEndProc();
void WaitforResponse(int playerid);
void RefreshMzone(int player, int flag = 0x881fff, int use_cache = 1);
void RefreshSzone(int player, int flag = 0x681fff, int use_cache = 1);
void RefreshHand(int player, int flag = 0x781fff, int use_cache = 1);
void RefreshGrave(int player, int flag = 0x81fff, int use_cache = 1);
void RefreshExtra(int player, int flag = 0x81fff, int use_cache = 1);
void RefreshSingle(int player, int location, int sequence, int flag = 0xf81fff);
static int MessageHandler(long fduel, int type);
static void RelayTimer(evutil_socket_t fd, short events, void* arg);
void PseudoRefreshDeck(int player, int flag = 0x181fff);
static std::vector<ReplayPacket> replay_stream;
protected:
class duelist {
public:
DuelPlayer* player;
bool ready;
Deck pdeck;
int deck_error;
duelist() : player(0), ready(false), deck_error(0) {}
duelist(DuelPlayer* _player) : player(_player), ready(false), deck_error(0) {}
};
duelist players[6];
unsigned char startp[2];
DuelPlayer* cur_player[2];
std::set<DuelPlayer*> observers;
unsigned char hand_result[2];
unsigned char last_response;
Replay last_replay;
Replay new_replay;
bool game_started;
unsigned char turn_count;
unsigned short time_limit[2];
unsigned short time_elapsed;
};
}
#endif //RELAY_DUEL_H
...@@ -295,6 +295,7 @@ ...@@ -295,6 +295,7 @@
!system 1244 Single Duel !system 1244 Single Duel
!system 1245 Match !system 1245 Match
!system 1246 Tag !system 1246 Tag
!system 1247 Relay
!system 1250 Host !system 1250 Host
!system 1251Duel !system 1251Duel
!system 1252Spectate !system 1252Spectate
......
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