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

update deck error handling (#2049)

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