Commit a69d6121 authored by nanahira's avatar nanahira

Merge branch 'master' into server

parents 0ca4b18f 2326c4c5
Pipeline #40708 passed with stages
in 18 minutes and 50 seconds
...@@ -1932,18 +1932,42 @@ bool DeckBuilder::check_limit(code_pointer pointer) { ...@@ -1932,18 +1932,42 @@ bool DeckBuilder::check_limit(code_pointer pointer) {
auto flit = filterList->content.find(limitcode); auto flit = filterList->content.find(limitcode);
if(flit != filterList->content.end()) if(flit != filterList->content.end())
limit = flit->second; limit = flit->second;
for (auto& card : deckManager.current_deck.main) { auto remaining_credits = filterList->credit_limits;
if (card->first == limitcode || card->second.alias == limitcode) auto limitcode_credit_it = filterList->credits.find(limitcode);
auto handle_card = [&](ygo::code_pointer& card) {
if (card->first == limitcode || card->second.alias == limitcode) {
limit--; limit--;
if(limit <= 0)
return false;
if(limitcode_credit_it != filterList->credits.end()) {
auto limitcode_credits = limitcode_credit_it->second;
for(auto& credit : limitcode_credits) {
auto key = credit.first;
auto remaining_credit_it = remaining_credits.find(key);
if(remaining_credit_it != remaining_credits.end()) {
auto value = credit.second;
auto remaining_credit = remaining_credit_it->second;
if(remaining_credit < value)
return false;
remaining_credits[key] -= value;
}
}
}
}
return true;
};
for (auto& card : deckManager.current_deck.main) {
if(!handle_card(card))
return false;
} }
for (auto& card : deckManager.current_deck.extra) { for (auto& card : deckManager.current_deck.extra) {
if (card->first == limitcode || card->second.alias == limitcode) if(!handle_card(card))
limit--; return false;
} }
for (auto& card : deckManager.current_deck.side) { for (auto& card : deckManager.current_deck.side) {
if (card->first == limitcode || card->second.alias == limitcode) if(!handle_card(card))
limit--; return false;
} }
return limit > 0; return true;
} }
} }
...@@ -8,10 +8,102 @@ namespace ygo { ...@@ -8,10 +8,102 @@ namespace ygo {
DeckManager deckManager; DeckManager deckManager;
void DeckManager::LoadLFListFromLineProvider(const std::function<bool(char*, size_t)>& getLine, bool insert) {
std::vector<LFList> loadedLists;
auto cur = loadedLists.rend();
char linebuf[256]{};
wchar_t strBuffer[256]{};
if(true) {
while(getLine(linebuf, sizeof linebuf)) {
if(linebuf[0] == '#')
continue;
if(linebuf[0] == '!') {
auto len = std::strcspn(linebuf, "\r\n");
linebuf[len] = 0;
BufferIO::DecodeUTF8(&linebuf[1], strBuffer);
LFList newlist;
newlist.listName = strBuffer;
newlist.hash = 0x7dfcee6a;
loadedLists.push_back(newlist);
cur = loadedLists.rbegin();
continue;
}
if(cur == loadedLists.rend())
continue;
if(linebuf[0] == '$') {
char* keyPos = linebuf + 1;
keyPos += std::strspn(keyPos, " \t");
auto keyLen = std::strcspn(keyPos, " \t\r\n");
if(!keyLen)
continue;
char keybuf[256];
if(keyLen >= sizeof keybuf)
keyLen = sizeof keybuf - 1;
std::memcpy(keybuf, keyPos, keyLen);
keybuf[keyLen] = 0;
keyPos += keyLen;
keyPos += std::strspn(keyPos, " \t");
errno = 0;
char* valuePos = keyPos;
auto limitValue = std::strtoul(keyPos, &keyPos, 10);
if(errno || valuePos == keyPos)
continue;
BufferIO::DecodeUTF8(keybuf, strBuffer);
cur->credit_limits[strBuffer] = static_cast<uint32_t>(limitValue);
continue;
}
char* pos = linebuf;
errno = 0;
char* codePos = pos;
auto result = std::strtoul(pos, &pos, 10);
if(errno || result > UINT32_MAX || codePos == pos)
continue;
if(*pos != ' ' && *pos != '\t')
continue;
pos += std::strspn(pos, " \t");
uint32_t code = static_cast<uint32_t>(result);
if(*pos == '$') {
++pos;
pos += std::strspn(pos, " \t");
auto creditKeyLen = std::strcspn(pos, " \t\r\n");
if(!creditKeyLen)
continue;
char keybuf[256];
if(creditKeyLen >= sizeof keybuf)
creditKeyLen = sizeof keybuf - 1;
std::memcpy(keybuf, pos, creditKeyLen);
keybuf[creditKeyLen] = 0;
pos += creditKeyLen;
pos += std::strspn(pos, " \t");
errno = 0;
char* creditValuePos = pos;
auto creditValue = std::strtoul(pos, &pos, 10);
if(errno || creditValuePos == pos)
continue;
BufferIO::DecodeUTF8(keybuf, strBuffer);
cur->credits[code][strBuffer] = static_cast<uint32_t>(creditValue);
continue;
}
errno = 0;
char* countPos = pos;
int count = std::strtol(pos, &pos, 10);
if(errno || countPos == pos)
continue;
if(count < 0 || count > 2)
continue;
cur->content[code] = count;
cur->hash = cur->hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + count)) | (code >> (5 - count)));
}
}
if(insert)
_lfList.insert(_lfList.begin(), loadedLists.begin(), loadedLists.end());
else
_lfList.insert(_lfList.end(), loadedLists.begin(), loadedLists.end());
}
void DeckManager::LoadLFListSingle(const char* path, bool insert) { void DeckManager::LoadLFListSingle(const char* path, bool insert) {
FILE* fp = myfopen(path, "r"); FILE* fp = myfopen(path, "r");
if (!fp) return; if (!fp) return;
_LoadLFListFromLineProvider([&](char* buf, size_t sz) { LoadLFListFromLineProvider([&](char* buf, size_t sz) {
return std::fgets(buf, sz, fp) != nullptr; return std::fgets(buf, sz, fp) != nullptr;
}, insert); }, insert);
std::fclose(fp); std::fclose(fp);
...@@ -19,7 +111,7 @@ void DeckManager::LoadLFListSingle(const char* path, bool insert) { ...@@ -19,7 +111,7 @@ void DeckManager::LoadLFListSingle(const char* path, bool insert) {
void DeckManager::LoadLFListSingle(const wchar_t* path, bool insert) { void DeckManager::LoadLFListSingle(const wchar_t* path, bool insert) {
FILE* fp = mywfopen(path, "r"); FILE* fp = mywfopen(path, "r");
if (!fp) return; if (!fp) return;
_LoadLFListFromLineProvider([&](char* buf, size_t sz) { LoadLFListFromLineProvider([&](char* buf, size_t sz) {
return std::fgets(buf, sz, fp) != nullptr; return std::fgets(buf, sz, fp) != nullptr;
}, insert); }, insert);
std::fclose(fp); std::fclose(fp);
...@@ -28,7 +120,7 @@ void DeckManager::LoadLFListSingle(const wchar_t* path, bool insert) { ...@@ -28,7 +120,7 @@ void DeckManager::LoadLFListSingle(const wchar_t* path, bool insert) {
void DeckManager::LoadLFListSingle(irr::io::IReadFile* reader, bool insert) { void DeckManager::LoadLFListSingle(irr::io::IReadFile* reader, bool insert) {
std::string linebuf; std::string linebuf;
char ch{}; char ch{};
_LoadLFListFromLineProvider([&](char* buf, size_t sz) { LoadLFListFromLineProvider([&](char* buf, size_t sz) {
while (reader->read(&ch, 1)) { while (reader->read(&ch, 1)) {
if (ch == '\0') break; if (ch == '\0') break;
linebuf.push_back(ch); linebuf.push_back(ch);
...@@ -97,6 +189,27 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r ...@@ -97,6 +189,27 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
if (!lflist) if (!lflist)
return 0; return 0;
auto& list = lflist->content; auto& list = lflist->content;
std::unordered_map<std::wstring, uint32_t> credit_used;
auto spend_credit = [&](uint32_t code) {
auto code_credit_it = lflist->credits.find(code);
if(code_credit_it == lflist->credits.end())
return (uint32_t)0;
auto code_credit = code_credit_it->second;
for(auto& credit_it : code_credit) {
auto key = credit_it.first;
auto credit_limit_it = lflist->credit_limits.find(key);
if(credit_limit_it == lflist->credit_limits.end())
continue;
auto credit_limit = credit_limit_it->second;
if(credit_used.find(key) == credit_used.end())
credit_used[key] = 0;
auto credit_after = credit_used[key] + credit_it.second;
if(credit_after > credit_limit)
return (DECKERROR_LFLIST << 28) | code;
credit_used[key] = credit_after;
}
return (uint32_t)0;
};
const unsigned int rule_map[6] = { AVAIL_OCG, AVAIL_TCG, AVAIL_SC, AVAIL_CUSTOM, AVAIL_OCGTCG, 0 }; const unsigned int rule_map[6] = { AVAIL_OCG, AVAIL_TCG, AVAIL_SC, AVAIL_CUSTOM, AVAIL_OCGTCG, 0 };
unsigned int avail = 0; unsigned int avail = 0;
if (rule >= 0 && rule < (int)(sizeof rule_map / sizeof rule_map[0])) if (rule >= 0 && rule < (int)(sizeof rule_map / sizeof rule_map[0]))
...@@ -115,6 +228,9 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r ...@@ -115,6 +228,9 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
auto it = list.find(code); auto it = list.find(code);
if(it != list.end() && dc > it->second) if(it != list.end() && dc > it->second)
return (DECKERROR_LFLIST << 28) | cit->first; return (DECKERROR_LFLIST << 28) | cit->first;
auto spend_credit_error = spend_credit(code);
if(spend_credit_error)
return spend_credit_error;
} }
for (auto& cit : deck.extra) { for (auto& cit : deck.extra) {
auto gameruleDeckError = checkAvail(cit->second.ot, avail); auto gameruleDeckError = checkAvail(cit->second.ot, avail);
...@@ -130,6 +246,9 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r ...@@ -130,6 +246,9 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
auto it = list.find(code); auto it = list.find(code);
if(it != list.end() && dc > it->second) if(it != list.end() && dc > it->second)
return (DECKERROR_LFLIST << 28) | cit->first; return (DECKERROR_LFLIST << 28) | cit->first;
auto spend_credit_error = spend_credit(code);
if(spend_credit_error)
return spend_credit_error;
} }
for (auto& cit : deck.side) { for (auto& cit : deck.side) {
auto gameruleDeckError = checkAvail(cit->second.ot, avail); auto gameruleDeckError = checkAvail(cit->second.ot, avail);
...@@ -145,6 +264,9 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r ...@@ -145,6 +264,9 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
auto it = list.find(code); auto it = list.find(code);
if(it != list.end() && dc > it->second) if(it != list.end() && dc > it->second)
return (DECKERROR_LFLIST << 28) | cit->first; return (DECKERROR_LFLIST << 28) | cit->first;
auto spend_credit_error = spend_credit(code);
if(spend_credit_error)
return spend_credit_error;
} }
return 0; return 0;
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <sstream> #include <sstream>
#include <functional>
#include "data_manager.h" #include "data_manager.h"
#include "bufferio.h" #include "bufferio.h"
...@@ -43,6 +44,8 @@ struct LFList { ...@@ -43,6 +44,8 @@ struct LFList {
unsigned int hash{}; unsigned int hash{};
std::wstring listName; std::wstring listName;
std::unordered_map<uint32_t, int> content; std::unordered_map<uint32_t, int> content;
std::unordered_map<std::wstring, uint32_t> credit_limits;
std::unordered_map<uint32_t, std::unordered_map<std::wstring, uint32_t>> credits;
}; };
struct Deck { struct Deck {
std::vector<code_pointer> main; std::vector<code_pointer> main;
...@@ -114,53 +117,7 @@ public: ...@@ -114,53 +117,7 @@ public:
#endif //YGOPRO_SERVER_MODE #endif //YGOPRO_SERVER_MODE
private: private:
template<typename LineProvider> void LoadLFListFromLineProvider(const std::function<bool(char*, size_t)>& getLine, bool insert = false);
void _LoadLFListFromLineProvider(LineProvider getLine, bool insert = false) {
std::vector<LFList> loadedLists;
auto cur = loadedLists.rend(); // 注意:在临时 list 上操作
char linebuf[256]{};
wchar_t strBuffer[256]{};
while (getLine(linebuf, sizeof(linebuf))) {
if (linebuf[0] == '#')
continue;
if (linebuf[0] == '!') {
auto len = std::strcspn(linebuf, "\r\n");
linebuf[len] = 0;
BufferIO::DecodeUTF8(&linebuf[1], strBuffer);
LFList newlist;
newlist.listName = strBuffer;
newlist.hash = 0x7dfcee6a;
loadedLists.push_back(newlist);
cur = loadedLists.rbegin();
continue;
}
if (cur == loadedLists.rend())
continue;
char* pos = linebuf;
errno = 0;
auto result = std::strtoul(pos, &pos, 10);
if (errno || result > UINT32_MAX)
continue;
if (pos == linebuf || *pos != ' ')
continue;
uint32_t code = static_cast<uint32_t>(result);
errno = 0;
int count = std::strtol(pos, &pos, 10);
if (errno)
continue;
if (count < 0 || count > 2)
continue;
cur->content[code] = count;
cur->hash = cur->hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + count)) | (code >> (5 - count)));
}
if (insert) {
_lfList.insert(_lfList.begin(), loadedLists.begin(), loadedLists.end());
} else {
_lfList.insert(_lfList.end(), loadedLists.begin(), loadedLists.end());
}
}
}; };
extern DeckManager deckManager; extern DeckManager deckManager;
......
...@@ -311,9 +311,6 @@ bool Game::Initialize() { ...@@ -311,9 +311,6 @@ bool Game::Initialize() {
wCreateHost->setVisible(false); wCreateHost->setVisible(false);
env->addStaticText(dataManager.GetSysString(1226), irr::core::rect<irr::s32>(20, 30, 220, 50), false, false, wCreateHost); env->addStaticText(dataManager.GetSysString(1226), irr::core::rect<irr::s32>(20, 30, 220, 50), false, false, wCreateHost);
cbHostLFlist = env->addComboBox(irr::core::rect<irr::s32>(140, 25, 300, 50), wCreateHost); cbHostLFlist = env->addComboBox(irr::core::rect<irr::s32>(140, 25, 300, 50), wCreateHost);
for(unsigned int i = 0; i < deckManager._lfList.size(); ++i)
cbHostLFlist->addItem(deckManager._lfList[i].listName.c_str(), deckManager._lfList[i].hash);
cbHostLFlist->setSelected(gameConf.use_lflist ? gameConf.default_lflist : cbHostLFlist->getItemCount() - 1);
env->addStaticText(dataManager.GetSysString(1225), irr::core::rect<irr::s32>(20, 60, 220, 80), false, false, wCreateHost); env->addStaticText(dataManager.GetSysString(1225), irr::core::rect<irr::s32>(20, 60, 220, 80), false, false, wCreateHost);
cbRule = env->addComboBox(irr::core::rect<irr::s32>(140, 55, 300, 80), wCreateHost); cbRule = env->addComboBox(irr::core::rect<irr::s32>(140, 55, 300, 80), wCreateHost);
cbRule->setMaxSelectionRows(10); cbRule->setMaxSelectionRows(10);
...@@ -1551,6 +1548,10 @@ void Game::RefreshLFList() { ...@@ -1551,6 +1548,10 @@ void Game::RefreshLFList() {
cbLFlist->addItem(deckManager._lfList[i].listName.c_str()); cbLFlist->addItem(deckManager._lfList[i].listName.c_str());
cbLFlist->setEnabled(gameConf.use_lflist); cbLFlist->setEnabled(gameConf.use_lflist);
cbLFlist->setSelected(gameConf.use_lflist ? gameConf.default_lflist : cbLFlist->getItemCount() - 1); cbLFlist->setSelected(gameConf.use_lflist ? gameConf.default_lflist : cbLFlist->getItemCount() - 1);
cbHostLFlist->clear();
for(unsigned int i = 0; i < deckManager._lfList.size(); ++i)
cbHostLFlist->addItem(deckManager._lfList[i].listName.c_str(), deckManager._lfList[i].hash);
cbHostLFlist->setSelected(gameConf.use_lflist ? gameConf.default_lflist : cbHostLFlist->getItemCount() - 1);
} }
void Game::RefreshBot() { void Game::RefreshBot() {
if(!gameConf.enable_bot_mode) if(!gameConf.enable_bot_mode)
......
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