Commit 6123e844 authored by edo9300's avatar edo9300

Added relay duel mode

parent b91f4976
......@@ -512,11 +512,17 @@ void Game::DrawMisc() {
recti p1size = mainGame->Resize(335, 31, 629, 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);
else
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);
p2size.UpperLeftCorner.X -= cld.Width;
textFont->draw(dInfo.clientname, p2size, 0xffffffff, false, false, 0);
......
......@@ -328,6 +328,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->env->addMessageBox(L"", msgbuf);
mainGame->cbDeckSelect->setEnabled(true);
mainGame->cbDeckSelect2->setEnabled(true);
if(mainGame->dInfo.isTag || mainGame->dInfo.isRelay)
mainGame->btnHostPrepDuelist->setEnabled(true);
mainGame->gMutex.Unlock();
break;
}
......@@ -554,20 +556,69 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
str.append(msgbuf);
}
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->chkHostPrepReady[2]->setVisible(true);
mainGame->chkHostPrepReady[3]->setVisible(true);
mainGame->stHostPrepDuelist[2]->setVisible(true);
mainGame->stHostPrepDuelist[3]->setVisible(true);
} else {
mainGame->dInfo.isRelay = false;
for (int i = 2; i < 4; ++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 < 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->chkHostPrepReady[2]->setVisible(false);
mainGame->chkHostPrepReady[3]->setVisible(false);
mainGame->stHostPrepDuelist[2]->setVisible(false);
mainGame->stHostPrepDuelist[3]->setVisible(false);
mainGame->dInfo.isRelay = true;
for (int i = 0; i < 3; ++i) {
mainGame->stHostPrepDuelist[i]->setRelativePosition(rect<s32>(40, 65 + i * 25, 240, 85 + i * 25));
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->btnHostPrepReady->setVisible(true);
mainGame->btnHostPrepNotReady->setVisible(false);
......@@ -584,6 +635,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->stHostPrepDuelist[1]->setText(L"");
mainGame->stHostPrepDuelist[2]->setText(L"");
mainGame->stHostPrepDuelist[3]->setText(L"");
mainGame->stHostPrepDuelist[4]->setText(L"");
mainGame->stHostPrepDuelist[5]->setText(L"");
mainGame->stHostPrepOB->setText(L"");
mainGame->SetStaticText(mainGame->stHostPrepRule, 180, mainGame->guiFont, (wchar_t*)str.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) {
}
case STOC_TYPE_CHANGE: {
STOC_TypeChange* pkt = (STOC_TypeChange*)pdata;
if(!mainGame->dInfo.isTag) {
if(!mainGame->dInfo.isTag && !mainGame->dInfo.isRelay) {
selftype = pkt->type & 0xf;
is_host = ((pkt->type >> 4) & 0xf) != 0;
mainGame->btnHostPrepKick[2]->setVisible(false);
mainGame->btnHostPrepKick[3]->setVisible(false);
mainGame->btnHostPrepKick[4]->setVisible(false);
mainGame->btnHostPrepKick[5]->setVisible(false);
if(is_host) {
mainGame->btnHostPrepStart->setVisible(true);
mainGame->btnHostPrepKick[0]->setVisible(true);
......@@ -647,7 +702,9 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
} else {
mainGame->btnHostPrepStart->setEnabled(false);
}
} else {
} else if (mainGame->dInfo.isTag) {
mainGame->btnHostPrepKick[4]->setVisible(false);
mainGame->btnHostPrepKick[5]->setVisible(false);
if(selftype < 4) {
mainGame->chkHostPrepReady[selftype]->setEnabled(false);
mainGame->chkHostPrepReady[selftype]->setChecked(false);
......@@ -680,6 +737,42 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
} else {
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;
break;
......@@ -699,6 +792,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->dInfo.time_left[0] = 0;
mainGame->dInfo.time_left[1] = 0;
mainGame->dInfo.time_player = 2;
mainGame->dInfo.relay_player[0] = 0;
mainGame->dInfo.relay_player[1] = 0;
mainGame->is_building = false;
mainGame->wCardImg->setVisible(true);
mainGame->wInfos->setVisible(true);
......@@ -717,7 +812,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->wChat->setVisible(true);
mainGame->device->setEventReceiver(&mainGame->dField);
mainGame->SetPhaseButtons();
if(!mainGame->dInfo.isTag) {
if(!mainGame->dInfo.isTag && !mainGame->dInfo.isRelay) {
if(selftype > 1) {
mainGame->dInfo.player_type = 7;
mainGame->btnLeaveGame->setText(dataManager.GetSysString(1350));
......@@ -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[0]->getText(), mainGame->dInfo.clientname, 20);
}
} else {
} else if(mainGame->dInfo.isTag) {
if(selftype > 3) {
mainGame->dInfo.player_type = 7;
mainGame->btnLeaveGame->setText(dataManager.GetSysString(1350));
......@@ -751,6 +846,32 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
}
mainGame->dInfo.tag_player[0] = 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();
match_kill = 0;
......@@ -890,11 +1011,16 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
case STOC_HS_PLAYER_ENTER: {
mainGame->PlaySoundEffect("./sound/playerenter.wav");
STOC_HS_PlayerEnter* pkt = (STOC_HS_PlayerEnter*)pdata;
if(pkt->pos > 3)
if(pkt->pos > 5)
break;
wchar_t 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)
BufferIO::CopyWStr(pkt->name, mainGame->dInfo.hostname, 20);
else if(pkt->pos == 1)
......@@ -918,7 +1044,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
STOC_HS_PlayerChange* pkt = (STOC_HS_PlayerChange*)pdata;
unsigned char pos = (pkt->status >> 4) & 0xf;
unsigned char state = pkt->status & 0xf;
if(pos > 3)
if(pos > 5)
break;
mainGame->gMutex.Lock();
if(state < 8) {
......@@ -927,14 +1053,21 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->stHostPrepDuelist[state]->setText(prename);
mainGame->stHostPrepDuelist[pos]->setText(L"");
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);
else if(pos == 1)
else if (pos == 1)
BufferIO::CopyWStr(prename, mainGame->dInfo.hostname_tag, 20);
else if(pos == 2)
else if (pos == 2)
BufferIO::CopyWStr(prename, mainGame->dInfo.clientname, 20);
else if(pos == 3)
else if (pos == 3)
BufferIO::CopyWStr(prename, mainGame->dInfo.clientname_tag, 20);
}
} else if(state == PLAYERCHANGE_READY) {
mainGame->chkHostPrepReady[pos]->setChecked(true);
if(pos == selftype) {
......@@ -958,8 +1091,10 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
mainGame->chkHostPrepReady[pos]->setChecked(false);
mainGame->stHostPrepOB->setText(watchbuf);
}
if(mainGame->chkHostPrepReady[0]->isChecked() && mainGame->chkHostPrepReady[1]->isChecked()
&& (!mainGame->dInfo.isTag || (mainGame->chkHostPrepReady[2]->isChecked() && mainGame->chkHostPrepReady[3]->isChecked()))) {
if((mainGame->chkHostPrepReady[0]->isChecked() && mainGame->chkHostPrepReady[1]->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);
} else {
mainGame->btnHostPrepStart->setEnabled(false);
......@@ -1181,7 +1316,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
if(match_kill)
myswprintf(vic_buf, dataManager.GetVictoryString(0x20), dataManager.GetName(match_kill));
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
myswprintf(vic_buf, L"%ls", dataManager.GetVictoryString(type));
mainGame->dInfo.vic_string = vic_buf;
......@@ -1190,7 +1325,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
if(match_kill)
myswprintf(vic_buf, dataManager.GetVictoryString(0x20), dataManager.GetName(match_kill));
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
myswprintf(vic_buf, L"%ls", dataManager.GetVictoryString(type));
mainGame->dInfo.vic_string = vic_buf;
......@@ -1223,7 +1358,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
}
if(playertype & 0xf0)
mainGame->dInfo.player_type = 7;
if(mainGame->dInfo.isTag) {
if(mainGame->dInfo.isTag && !mainGame->dInfo.isRelay) {
if(mainGame->dInfo.isFirst)
mainGame->dInfo.tag_player[1] = true;
else
......@@ -2456,7 +2591,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
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)
mainGame->dInfo.tag_player[0] = !mainGame->dInfo.tag_player[0];
else
......@@ -3667,7 +3802,13 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
return true;
}
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 ecount = (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) {
}
mainGame->WaitFrameSignal(5);
}
if(mainGame->dInfo.isRelay)
mainGame->dInfo.relay_player[player] = newp;
break;
}
case MSG_RELOAD_FIELD: {
......
......@@ -1848,12 +1848,16 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
if(mplayer >= 0) {
const wchar_t* player_name;
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;
else
player_name = mainGame->dInfo.hostname_tag;
} 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;
else
player_name = mainGame->dInfo.clientname_tag;
......
......@@ -155,6 +155,7 @@ bool Game::Initialize() {
cbMatchMode->addItem(dataManager.GetSysString(1244));
cbMatchMode->addItem(dataManager.GetSysString(1245));
cbMatchMode->addItem(dataManager.GetSysString(1246));
cbMatchMode->addItem(dataManager.GetSysString(1247));
env->addStaticText(dataManager.GetSysString(1237), rect<s32>(20, 120, 320, 140), false, false, wCreateHost);
myswprintf(strbuf, L"%d", 180);
ebTimeLimit = env->addEditBox(strbuf, rect<s32>(140, 115, 220, 140), true, wCreateHost);
......@@ -237,23 +238,17 @@ bool Game::Initialize() {
wHostPrepare2->setVisible(false);
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));
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);
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]->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));
myswprintf(dataManager.strBuffer, L"%ls%d", dataManager.GetSysString(1253), 0);
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);
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->setMaxSelectionRows(10);
cbDeckSelect2 = env->addComboBox(rect<s32>(280, 230, 430, 255), wHostPrepare);
......@@ -1362,22 +1357,22 @@ void Game::AddChatMsg(wchar_t* msg, int player) {
chatType[0] = player;
switch(player) {
case 0: //from host
chatMsg[0].append(dInfo.hostname);
chatMsg[0].append((dInfo.isRelay) ? dInfo.hostname_relay[0] : dInfo.hostname);
chatMsg[0].append(L": ");
break;
case 1: //from client
PlaySoundEffect("./sound/chatmessage.wav");
chatMsg[0].append(dInfo.clientname);
chatMsg[0].append((dInfo.isRelay) ? dInfo.clientname_relay[0] : dInfo.clientname);
chatMsg[0].append(L": ");
break;
case 2: //host tag
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": ");
break;
case 3: //client tag
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": ");
break;
case 7: //local name
......@@ -1662,8 +1657,13 @@ void Game::OnResize() {
wLanWindow->setRelativePosition(ResizeWin(220, 100, 800, 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));
wHostPrepare2->setRelativePosition(ResizeWin(750, 120, 950, 440));
}
wRules->setRelativePosition(ResizeWin(630, 100, 1000, 310));
wCustomRules->setRelativePosition(ResizeWin(700, 100, 910, 410));
wReplay->setRelativePosition(ResizeWin(220, 100, 800, 520));
......
......@@ -52,10 +52,12 @@ struct DuelInfo {
bool isReplaySkiping;
bool isFirst;
bool isTag;
bool isRelay;
bool isSingleMode;
bool lua64;
bool is_shuffling;
bool tag_player[2];
int relay_player[2];
int lp[2];
int startlp;
int duel_field;
......@@ -66,6 +68,8 @@ struct DuelInfo {
wchar_t clientname[20];
wchar_t hostname_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* vic_string;
unsigned char player_type;
......@@ -301,14 +305,15 @@ public:
irr::gui::IGUIStaticText* stHostCardRule;
irr::gui::IGUIButton* btnHostPrepDuelist;
irr::gui::IGUIButton* btnHostPrepOB;
irr::gui::IGUIStaticText* stHostPrepDuelist[4];
irr::gui::IGUICheckBox* chkHostPrepReady[4];
irr::gui::IGUIButton* btnHostPrepKick[4];
irr::gui::IGUIStaticText* stHostPrepDuelist[6];
irr::gui::IGUICheckBox* chkHostPrepReady[6];
irr::gui::IGUIButton* btnHostPrepKick[6];
irr::gui::IGUIComboBox* cbDeckSelect;
irr::gui::IGUIComboBox* cbDeckSelect2;
irr::gui::IGUIStaticText* stHostPrepRule;
irr::gui::IGUIStaticText* stHostPrepRule2;
irr::gui::IGUIStaticText* stHostPrepOB;
irr::gui::IGUIStaticText* stDeckSelect;
irr::gui::IGUIButton* btnHostPrepReady;
irr::gui::IGUIButton* btnHostPrepNotReady;
irr::gui::IGUIButton* btnHostPrepStart;
......
......@@ -226,11 +226,17 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
UpdateDeck();
DuelClient::SendPacketToServer(CTOS_HS_READY);
mainGame->cbDeckSelect->setEnabled(false);
mainGame->cbDeckSelect2->setEnabled(false);
if(mainGame->dInfo.isTag || mainGame->dInfo.isRelay)
mainGame->btnHostPrepDuelist->setEnabled(false);
break;
}
case BUTTON_HP_NOTREADY: {
DuelClient::SendPacketToServer(CTOS_HS_NOTREADY);
mainGame->cbDeckSelect->setEnabled(true);
mainGame->cbDeckSelect2->setEnabled(true);
if(mainGame->dInfo.isTag || mainGame->dInfo.isRelay)
mainGame->btnHostPrepDuelist->setEnabled(true);
break;
}
case BUTTON_HP_START: {
......@@ -425,10 +431,14 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
DuelClient::SendPacketToServer(CTOS_HS_READY);
mainGame->cbDeckSelect->setEnabled(false);
mainGame->cbDeckSelect2->setEnabled(false);
if(mainGame->dInfo.isTag || mainGame->dInfo.isRelay)
mainGame->btnHostPrepDuelist->setEnabled(false);
} else {
DuelClient::SendPacketToServer(CTOS_HS_NOTREADY);
mainGame->cbDeckSelect->setEnabled(true);
mainGame->cbDeckSelect2->setEnabled(true);
if(mainGame->dInfo.isTag || mainGame->dInfo.isRelay)
mainGame->btnHostPrepDuelist->setEnabled(true);
}
break;
}
......
#include "netserver.h"
#include "single_duel.h"
#include "tag_duel.h"
#include "relay_duel.h"
namespace ygo {
std::unordered_map<bufferevent*, DuelPlayer> NetServer::users;
......@@ -232,10 +233,13 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, char* data, unsigned int len) {
} else if(pkt->info.mode == MODE_TAG) {
duel_mode = new TagDuel();
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)
pkt->info.rule = 0;
if(pkt->info.mode > 2)
if(pkt->info.mode > 3)
pkt->info.mode = 0;
unsigned int hash = 1;
for(auto lfit = deckManager._lfList.begin(); lfit != deckManager._lfList.end(); ++lfit) {
......
......@@ -241,4 +241,5 @@ public:
#define MODE_SINGLE 0x0
#define MODE_MATCH 0x1
#define MODE_TAG 0x2
#define MODE_RELAY 0x3
#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 @@
!system 1244 Single Duel
!system 1245 Match
!system 1246 Tag
!system 1247 Relay
!system 1250 Host
!system 1251Duel
!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