Commit 59001686 authored by mercury233's avatar mercury233 Committed by GitHub

update deck error handling (#2049)

parent eb81f081
#include "deck_manager.h"
#include "data_manager.h"
#include "network.h"
#include "game.h"
#include <algorithm>
......@@ -61,7 +62,7 @@ wchar_t* DeckManager::GetLFListName(int lfhash) {
}
return (wchar_t*)dataManager.unknown_string;
}
int DeckManager::CheckLFList(Deck& deck, int lfhash, bool allow_ocg, bool allow_tcg) {
int DeckManager::CheckDeck(Deck& deck, int lfhash, bool allow_ocg, bool allow_tcg) {
std::unordered_map<int, int> ccount;
std::unordered_map<int, int>* list = 0;
for(size_t i = 0; i < _lfList.size(); ++i) {
......@@ -73,53 +74,73 @@ int DeckManager::CheckLFList(Deck& deck, int lfhash, bool allow_ocg, bool allow_
if(!list)
return 0;
int dc = 0;
if(deck.main.size() < 40 || deck.main.size() > 60 || deck.extra.size() > 15 || deck.side.size() > 15)
return 1;
if(deck.main.size() < 40 || deck.main.size() > 60)
return (DECKERROR_MAINCOUNT << 28) + deck.main.size();
if(deck.extra.size() > 15)
return (DECKERROR_EXTRACOUNT << 28) + deck.extra.size();
if(deck.side.size() > 15)
return (DECKERROR_SIDECOUNT << 28) + deck.side.size();
for(size_t i = 0; i < deck.main.size(); ++i) {
code_pointer cit = deck.main[i];
if((!allow_ocg && (cit->second.ot == 0x1)) || (!allow_tcg && (cit->second.ot == 0x2)))
return cit->first;
if(!allow_ocg && (cit->second.ot == 0x1))
return (DECKERROR_OCGONLY << 28) + cit->first;
if(!allow_tcg && (cit->second.ot == 0x2))
return (DECKERROR_TCGONLY << 28) + cit->first;
if(cit->second.type & (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ | TYPE_TOKEN | TYPE_LINK))
return 1;
return (DECKERROR_EXTRACOUNT << 28);
int code = cit->second.alias ? cit->second.alias : cit->first;
ccount[code]++;
dc = ccount[code];
if(dc > 3)
return (DECKERROR_CARDCOUNT << 28) + cit->first;
auto it = list->find(code);
if(dc > 3 || (it != list->end() && dc > it->second))
return cit->first;
if(it != list->end() && dc > it->second)
return (DECKERROR_LFLIST << 28) + cit->first;
}
for(size_t i = 0; i < deck.extra.size(); ++i) {
code_pointer cit = deck.extra[i];
if((!allow_ocg && (cit->second.ot == 0x1)) || (!allow_tcg && (cit->second.ot == 0x2)))
return cit->first;
if(!allow_ocg && (cit->second.ot == 0x1))
return (DECKERROR_OCGONLY << 28) + cit->first;
if(!allow_tcg && (cit->second.ot == 0x2))
return (DECKERROR_TCGONLY << 28) + cit->first;
int code = cit->second.alias ? cit->second.alias : cit->first;
ccount[code]++;
dc = ccount[code];
if(dc > 3)
return (DECKERROR_CARDCOUNT << 28) + cit->first;
auto it = list->find(code);
if(dc > 3 || (it != list->end() && dc > it->second))
return cit->first;
if(it != list->end() && dc > it->second)
return (DECKERROR_LFLIST << 28) + cit->first;
}
for(size_t i = 0; i < deck.side.size(); ++i) {
code_pointer cit = deck.side[i];
if((!allow_ocg && (cit->second.ot == 0x1)) || (!allow_tcg && (cit->second.ot == 0x2)))
return cit->first;
if(!allow_ocg && (cit->second.ot == 0x1))
return (DECKERROR_OCGONLY << 28) + cit->first;
if(!allow_tcg && (cit->second.ot == 0x2))
return (DECKERROR_TCGONLY << 28) + cit->first;
int code = cit->second.alias ? cit->second.alias : cit->first;
ccount[code]++;
dc = ccount[code];
if(dc > 3)
return (DECKERROR_CARDCOUNT << 28) + cit->first;
auto it = list->find(code);
if(dc > 3 || (it != list->end() && dc > it->second))
return cit->first;
if(it != list->end() && dc > it->second)
return (DECKERROR_LFLIST << 28) + cit->first;
}
return 0;
}
void DeckManager::LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec) {
int DeckManager::LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec) {
deck.clear();
int code;
int errorcode = 0;
CardData cd;
for(int i = 0; i < mainc; ++i) {
code = dbuf[i];
if(!dataManager.GetData(code, &cd))
if(!dataManager.GetData(code, &cd)) {
errorcode = code;
continue;
}
if(cd.type & TYPE_TOKEN)
continue;
else if(cd.type & (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ | TYPE_LINK) && deck.extra.size() < 15) {
......@@ -130,13 +151,16 @@ void DeckManager::LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec) {
}
for(int i = 0; i < sidec; ++i) {
code = dbuf[mainc + i];
if(!dataManager.GetData(code, &cd))
if(!dataManager.GetData(code, &cd)) {
errorcode = code;
continue;
}
if(cd.type & TYPE_TOKEN)
continue;
if(deck.side.size() < 15)
deck.side.push_back(dataManager.GetCodePointer(code)); //verified by GetData()
}
return errorcode;
}
bool DeckManager::LoadSide(Deck& deck, int* dbuf, int mainc, int sidec) {
std::unordered_map<int, int> pcount;
......
......@@ -37,8 +37,8 @@ public:
void LoadLFList();
wchar_t* GetLFListName(int lfhash);
int CheckLFList(Deck& deck, int lfhash, bool allow_ocg, bool allow_tcg);
void LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec);
int CheckDeck(Deck& deck, int lfhash, bool allow_ocg, bool allow_tcg);
int LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec);
bool LoadSide(Deck& deck, int* dbuf, int mainc, int sidec);
FILE* OpenDeckFile(const wchar_t * file, const char * mode);
bool LoadDeck(const wchar_t* file);
......
......@@ -216,13 +216,52 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
}
case ERRMSG_DECKERROR: {
mainGame->gMutex.Lock();
if(pkt->code == 1)
mainGame->env->addMessageBox(L"", dataManager.GetSysString(1406));
else {
wchar_t msgbuf[256];
myswprintf(msgbuf, dataManager.GetSysString(1407), dataManager.GetName(pkt->code));
mainGame->env->addMessageBox(L"", msgbuf);
unsigned int code = pkt->code & 0xFFFFFFF;
int flag = pkt->code >> 28;
wchar_t msgbuf[256];
switch(flag)
{
case DECKERROR_LFLIST: {
myswprintf(msgbuf, dataManager.GetSysString(1407), dataManager.GetName(code));
break;
}
case DECKERROR_OCGONLY: {
myswprintf(msgbuf, dataManager.GetSysString(1413), dataManager.GetName(code));
break;
}
case DECKERROR_TCGONLY: {
myswprintf(msgbuf, dataManager.GetSysString(1414), dataManager.GetName(code));
break;
}
case DECKERROR_UNKNOWNCARD: {
myswprintf(msgbuf, dataManager.GetSysString(1415), dataManager.GetName(code), code);
break;
}
case DECKERROR_CARDCOUNT: {
myswprintf(msgbuf, dataManager.GetSysString(1416), dataManager.GetName(code));
break;
}
case DECKERROR_MAINCOUNT: {
myswprintf(msgbuf, dataManager.GetSysString(1417), code);
break;
}
case DECKERROR_EXTRACOUNT: {
if(code>0)
myswprintf(msgbuf, dataManager.GetSysString(1418), code);
else
myswprintf(msgbuf, dataManager.GetSysString(1420));
break;
}
case DECKERROR_SIDECOUNT: {
myswprintf(msgbuf, dataManager.GetSysString(1419), code);
break;
}
default: {
myswprintf(msgbuf, dataManager.GetSysString(1406));
break;
}
}
mainGame->env->addMessageBox(L"", msgbuf);
mainGame->cbDeckSelect->setEnabled(true);
mainGame->gMutex.Unlock();
break;
......
......@@ -207,6 +207,15 @@ public:
#define ERRMSG_SIDEERROR 0x3
#define ERRMSG_VERERROR 0x4
#define DECKERROR_LFLIST 0x1
#define DECKERROR_OCGONLY 0x2
#define DECKERROR_TCGONLY 0x3
#define DECKERROR_UNKNOWNCARD 0x4
#define DECKERROR_CARDCOUNT 0x5
#define DECKERROR_MAINCOUNT 0x6
#define DECKERROR_EXTRACOUNT 0x7
#define DECKERROR_SIDECOUNT 0x8
#define MODE_SINGLE 0x0
#define MODE_MATCH 0x1
#define MODE_TAG 0x2
......
......@@ -252,16 +252,23 @@ void SingleDuel::PlayerReady(DuelPlayer* dp, bool is_ready) {
if(ready[dp->type] == is_ready)
return;
if(is_ready) {
bool allow_ocg = host_info.rule == 0 || host_info.rule == 2;
bool allow_tcg = host_info.rule == 1 || host_info.rule == 2;
int res = host_info.no_check_deck ? false : deckManager.CheckLFList(pdeck[dp->type], host_info.lflist, allow_ocg, allow_tcg);
if(res) {
unsigned int deckerror = 0;
if(!host_info.no_check_deck) {
if(deck_error[dp->type]) {
deckerror = (DECKERROR_UNKNOWNCARD << 28) + deck_error[dp->type];
} 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(pdeck[dp->type], host_info.lflist, allow_ocg, allow_tcg);
}
}
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 = res;
scem.code = deckerror;
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
return;
}
......@@ -287,7 +294,7 @@ void SingleDuel::UpdateDeck(DuelPlayer* dp, void* pdata) {
int mainc = BufferIO::ReadInt32(deckbuf);
int sidec = BufferIO::ReadInt32(deckbuf);
if(duel_count == 0) {
deckManager.LoadDeck(pdeck[dp->type], (int*)deckbuf, mainc, sidec);
deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], (int*)deckbuf, mainc, sidec);
} else {
if(deckManager.LoadSide(pdeck[dp->type], (int*)deckbuf, mainc, sidec)) {
ready[dp->type] = true;
......
......@@ -46,6 +46,7 @@ protected:
DuelPlayer* pplayer[2];
bool ready[2];
Deck pdeck[2];
int deck_error[2];
unsigned char hand_result[2];
unsigned char last_response;
std::set<DuelPlayer*> observers;
......
......@@ -222,16 +222,23 @@ void TagDuel::PlayerReady(DuelPlayer* dp, bool is_ready) {
if(dp->type > 3 || ready[dp->type] == is_ready)
return;
if(is_ready) {
bool allow_ocg = host_info.rule == 0 || host_info.rule == 2;
bool allow_tcg = host_info.rule == 1 || host_info.rule == 2;
int res = host_info.no_check_deck ? false : deckManager.CheckLFList(pdeck[dp->type], host_info.lflist, allow_ocg, allow_tcg);
if(res) {
unsigned int deckerror = 0;
if(!host_info.no_check_deck) {
if(deck_error[dp->type]) {
deckerror = (DECKERROR_UNKNOWNCARD << 28) + deck_error[dp->type];
} 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(pdeck[dp->type], host_info.lflist, allow_ocg, allow_tcg);
}
}
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 = res;
scem.code = deckerror;
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
return;
}
......@@ -256,7 +263,7 @@ void TagDuel::UpdateDeck(DuelPlayer* dp, void* pdata) {
char* deckbuf = (char*)pdata;
int mainc = BufferIO::ReadInt32(deckbuf);
int sidec = BufferIO::ReadInt32(deckbuf);
deckManager.LoadDeck(pdeck[dp->type], (int*)deckbuf, mainc, sidec);
deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], (int*)deckbuf, mainc, sidec);
}
void TagDuel::StartDuel(DuelPlayer* dp) {
if(dp != host_player)
......
......@@ -48,6 +48,7 @@ protected:
std::set<DuelPlayer*> observers;
bool ready[4];
Deck pdeck[4];
int deck_error[4];
unsigned char hand_result[2];
unsigned char last_response;
Replay last_replay;
......
......@@ -383,12 +383,20 @@
!system 1404 密码错误。
!system 1405 主机拒绝了连接。
!system 1406 无效卡组。
!system 1407 「%ls」的数量不符合当前设定。
!system 1407 「%ls」的数量不符合当前禁限卡表设定。
!system 1408 更换副卡组失败。
!system 1409 等待更换副卡组中...
!system 1410 卡组数量与先前不符合。
!system 1411 版本不匹配(%X.0%X.%X)。
!system 1412 无法解析主机地址。
!system 1413 「%ls」为OCG独有卡,不允许在当前设定下使用。
!system 1414 「%ls」为TCG独有卡,不允许在当前设定下使用。
!system 1415 卡组中「%ls(%d)」无法被主机识别。
!system 1416 卡组中「%ls」的总数量超过3张。
!system 1417 主卡组数量应为40-60张,当前卡组数量为%d张。
!system 1418 额外卡组数量应不超过15张,当前卡组数量为%d张。
!system 1419 副卡组数量应不超过15张,当前卡组数量为%d张。
!system 1420 有额外卡组卡片存在于主卡组,可能是额外卡组数量超过15张。
!system 1500 决斗结束。
!system 1501 录像结束。
!system 1502 连接已断开。
......
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