Skip to content

Commit a69d612

Browse files
Merge branch 'master' into server
2 parents 0ca4b18 + 2326c4c commit a69d612

File tree

4 files changed

+164
-60
lines changed

4 files changed

+164
-60
lines changed

gframe/deck_con.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,18 +1932,42 @@ bool DeckBuilder::check_limit(code_pointer pointer) {
19321932
auto flit = filterList->content.find(limitcode);
19331933
if(flit != filterList->content.end())
19341934
limit = flit->second;
1935-
for (auto& card : deckManager.current_deck.main) {
1936-
if (card->first == limitcode || card->second.alias == limitcode)
1935+
auto remaining_credits = filterList->credit_limits;
1936+
auto limitcode_credit_it = filterList->credits.find(limitcode);
1937+
auto handle_card = [&](ygo::code_pointer& card) {
1938+
if (card->first == limitcode || card->second.alias == limitcode) {
19371939
limit--;
1940+
if(limit <= 0)
1941+
return false;
1942+
if(limitcode_credit_it != filterList->credits.end()) {
1943+
auto limitcode_credits = limitcode_credit_it->second;
1944+
for(auto& credit : limitcode_credits) {
1945+
auto key = credit.first;
1946+
auto remaining_credit_it = remaining_credits.find(key);
1947+
if(remaining_credit_it != remaining_credits.end()) {
1948+
auto value = credit.second;
1949+
auto remaining_credit = remaining_credit_it->second;
1950+
if(remaining_credit < value)
1951+
return false;
1952+
remaining_credits[key] -= value;
1953+
}
1954+
}
1955+
}
1956+
}
1957+
return true;
1958+
};
1959+
for (auto& card : deckManager.current_deck.main) {
1960+
if(!handle_card(card))
1961+
return false;
19381962
}
19391963
for (auto& card : deckManager.current_deck.extra) {
1940-
if (card->first == limitcode || card->second.alias == limitcode)
1941-
limit--;
1964+
if(!handle_card(card))
1965+
return false;
19421966
}
19431967
for (auto& card : deckManager.current_deck.side) {
1944-
if (card->first == limitcode || card->second.alias == limitcode)
1945-
limit--;
1968+
if(!handle_card(card))
1969+
return false;
19461970
}
1947-
return limit > 0;
1971+
return true;
19481972
}
19491973
}

gframe/deck_manager.cpp

Lines changed: 125 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,110 @@ namespace ygo {
88

99
DeckManager deckManager;
1010

11+
void DeckManager::LoadLFListFromLineProvider(const std::function<bool(char*, size_t)>& getLine, bool insert) {
12+
std::vector<LFList> loadedLists;
13+
auto cur = loadedLists.rend();
14+
char linebuf[256]{};
15+
wchar_t strBuffer[256]{};
16+
if(true) {
17+
while(getLine(linebuf, sizeof linebuf)) {
18+
if(linebuf[0] == '#')
19+
continue;
20+
if(linebuf[0] == '!') {
21+
auto len = std::strcspn(linebuf, "\r\n");
22+
linebuf[len] = 0;
23+
BufferIO::DecodeUTF8(&linebuf[1], strBuffer);
24+
LFList newlist;
25+
newlist.listName = strBuffer;
26+
newlist.hash = 0x7dfcee6a;
27+
loadedLists.push_back(newlist);
28+
cur = loadedLists.rbegin();
29+
continue;
30+
}
31+
if(cur == loadedLists.rend())
32+
continue;
33+
if(linebuf[0] == '$') {
34+
char* keyPos = linebuf + 1;
35+
keyPos += std::strspn(keyPos, " \t");
36+
auto keyLen = std::strcspn(keyPos, " \t\r\n");
37+
if(!keyLen)
38+
continue;
39+
char keybuf[256];
40+
if(keyLen >= sizeof keybuf)
41+
keyLen = sizeof keybuf - 1;
42+
std::memcpy(keybuf, keyPos, keyLen);
43+
keybuf[keyLen] = 0;
44+
keyPos += keyLen;
45+
keyPos += std::strspn(keyPos, " \t");
46+
errno = 0;
47+
char* valuePos = keyPos;
48+
auto limitValue = std::strtoul(keyPos, &keyPos, 10);
49+
if(errno || valuePos == keyPos)
50+
continue;
51+
BufferIO::DecodeUTF8(keybuf, strBuffer);
52+
cur->credit_limits[strBuffer] = static_cast<uint32_t>(limitValue);
53+
continue;
54+
}
55+
char* pos = linebuf;
56+
errno = 0;
57+
char* codePos = pos;
58+
auto result = std::strtoul(pos, &pos, 10);
59+
if(errno || result > UINT32_MAX || codePos == pos)
60+
continue;
61+
if(*pos != ' ' && *pos != '\t')
62+
continue;
63+
pos += std::strspn(pos, " \t");
64+
uint32_t code = static_cast<uint32_t>(result);
65+
if(*pos == '$') {
66+
++pos;
67+
pos += std::strspn(pos, " \t");
68+
auto creditKeyLen = std::strcspn(pos, " \t\r\n");
69+
if(!creditKeyLen)
70+
continue;
71+
char keybuf[256];
72+
if(creditKeyLen >= sizeof keybuf)
73+
creditKeyLen = sizeof keybuf - 1;
74+
std::memcpy(keybuf, pos, creditKeyLen);
75+
keybuf[creditKeyLen] = 0;
76+
pos += creditKeyLen;
77+
pos += std::strspn(pos, " \t");
78+
errno = 0;
79+
char* creditValuePos = pos;
80+
auto creditValue = std::strtoul(pos, &pos, 10);
81+
if(errno || creditValuePos == pos)
82+
continue;
83+
BufferIO::DecodeUTF8(keybuf, strBuffer);
84+
cur->credits[code][strBuffer] = static_cast<uint32_t>(creditValue);
85+
continue;
86+
}
87+
errno = 0;
88+
char* countPos = pos;
89+
int count = std::strtol(pos, &pos, 10);
90+
if(errno || countPos == pos)
91+
continue;
92+
if(count < 0 || count > 2)
93+
continue;
94+
cur->content[code] = count;
95+
cur->hash = cur->hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + count)) | (code >> (5 - count)));
96+
}
97+
}
98+
if(insert)
99+
_lfList.insert(_lfList.begin(), loadedLists.begin(), loadedLists.end());
100+
else
101+
_lfList.insert(_lfList.end(), loadedLists.begin(), loadedLists.end());
102+
}
11103
void DeckManager::LoadLFListSingle(const char* path, bool insert) {
12104
FILE* fp = myfopen(path, "r");
13105
if (!fp) return;
14-
_LoadLFListFromLineProvider([&](char* buf, size_t sz) {
106+
LoadLFListFromLineProvider([&](char* buf, size_t sz) {
15107
return std::fgets(buf, sz, fp) != nullptr;
16108
}, insert);
17109
std::fclose(fp);
18110
}
19111
void DeckManager::LoadLFListSingle(const wchar_t* path, bool insert) {
20112
FILE* fp = mywfopen(path, "r");
21113
if (!fp) return;
22-
_LoadLFListFromLineProvider([&](char* buf, size_t sz) {
114+
LoadLFListFromLineProvider([&](char* buf, size_t sz) {
23115
return std::fgets(buf, sz, fp) != nullptr;
24116
}, insert);
25117
std::fclose(fp);
@@ -28,7 +120,7 @@ void DeckManager::LoadLFListSingle(const wchar_t* path, bool insert) {
28120
void DeckManager::LoadLFListSingle(irr::io::IReadFile* reader, bool insert) {
29121
std::string linebuf;
30122
char ch{};
31-
_LoadLFListFromLineProvider([&](char* buf, size_t sz) {
123+
LoadLFListFromLineProvider([&](char* buf, size_t sz) {
32124
while (reader->read(&ch, 1)) {
33125
if (ch == '\0') break;
34126
linebuf.push_back(ch);
@@ -97,6 +189,27 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
97189
if (!lflist)
98190
return 0;
99191
auto& list = lflist->content;
192+
std::unordered_map<std::wstring, uint32_t> credit_used;
193+
auto spend_credit = [&](uint32_t code) {
194+
auto code_credit_it = lflist->credits.find(code);
195+
if(code_credit_it == lflist->credits.end())
196+
return (uint32_t)0;
197+
auto code_credit = code_credit_it->second;
198+
for(auto& credit_it : code_credit) {
199+
auto key = credit_it.first;
200+
auto credit_limit_it = lflist->credit_limits.find(key);
201+
if(credit_limit_it == lflist->credit_limits.end())
202+
continue;
203+
auto credit_limit = credit_limit_it->second;
204+
if(credit_used.find(key) == credit_used.end())
205+
credit_used[key] = 0;
206+
auto credit_after = credit_used[key] + credit_it.second;
207+
if(credit_after > credit_limit)
208+
return (DECKERROR_LFLIST << 28) | code;
209+
credit_used[key] = credit_after;
210+
}
211+
return (uint32_t)0;
212+
};
100213
const unsigned int rule_map[6] = { AVAIL_OCG, AVAIL_TCG, AVAIL_SC, AVAIL_CUSTOM, AVAIL_OCGTCG, 0 };
101214
unsigned int avail = 0;
102215
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
115228
auto it = list.find(code);
116229
if(it != list.end() && dc > it->second)
117230
return (DECKERROR_LFLIST << 28) | cit->first;
231+
auto spend_credit_error = spend_credit(code);
232+
if(spend_credit_error)
233+
return spend_credit_error;
118234
}
119235
for (auto& cit : deck.extra) {
120236
auto gameruleDeckError = checkAvail(cit->second.ot, avail);
@@ -130,6 +246,9 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
130246
auto it = list.find(code);
131247
if(it != list.end() && dc > it->second)
132248
return (DECKERROR_LFLIST << 28) | cit->first;
249+
auto spend_credit_error = spend_credit(code);
250+
if(spend_credit_error)
251+
return spend_credit_error;
133252
}
134253
for (auto& cit : deck.side) {
135254
auto gameruleDeckError = checkAvail(cit->second.ot, avail);
@@ -145,6 +264,9 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
145264
auto it = list.find(code);
146265
if(it != list.end() && dc > it->second)
147266
return (DECKERROR_LFLIST << 28) | cit->first;
267+
auto spend_credit_error = spend_credit(code);
268+
if(spend_credit_error)
269+
return spend_credit_error;
148270
}
149271
return 0;
150272
}

gframe/deck_manager.h

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <unordered_map>
55
#include <vector>
66
#include <sstream>
7+
#include <functional>
78
#include "data_manager.h"
89
#include "bufferio.h"
910

@@ -43,6 +44,8 @@ struct LFList {
4344
unsigned int hash{};
4445
std::wstring listName;
4546
std::unordered_map<uint32_t, int> content;
47+
std::unordered_map<std::wstring, uint32_t> credit_limits;
48+
std::unordered_map<uint32_t, std::unordered_map<std::wstring, uint32_t>> credits;
4649
};
4750
struct Deck {
4851
std::vector<code_pointer> main;
@@ -114,53 +117,7 @@ class DeckManager {
114117
#endif //YGOPRO_SERVER_MODE
115118

116119
private:
117-
template<typename LineProvider>
118-
void _LoadLFListFromLineProvider(LineProvider getLine, bool insert = false) {
119-
std::vector<LFList> loadedLists;
120-
auto cur = loadedLists.rend(); // 注意:在临时 list 上操作
121-
char linebuf[256]{};
122-
wchar_t strBuffer[256]{};
123-
124-
while (getLine(linebuf, sizeof(linebuf))) {
125-
if (linebuf[0] == '#')
126-
continue;
127-
if (linebuf[0] == '!') {
128-
auto len = std::strcspn(linebuf, "\r\n");
129-
linebuf[len] = 0;
130-
BufferIO::DecodeUTF8(&linebuf[1], strBuffer);
131-
LFList newlist;
132-
newlist.listName = strBuffer;
133-
newlist.hash = 0x7dfcee6a;
134-
loadedLists.push_back(newlist);
135-
cur = loadedLists.rbegin();
136-
continue;
137-
}
138-
if (cur == loadedLists.rend())
139-
continue;
140-
char* pos = linebuf;
141-
errno = 0;
142-
auto result = std::strtoul(pos, &pos, 10);
143-
if (errno || result > UINT32_MAX)
144-
continue;
145-
if (pos == linebuf || *pos != ' ')
146-
continue;
147-
uint32_t code = static_cast<uint32_t>(result);
148-
errno = 0;
149-
int count = std::strtol(pos, &pos, 10);
150-
if (errno)
151-
continue;
152-
if (count < 0 || count > 2)
153-
continue;
154-
cur->content[code] = count;
155-
cur->hash = cur->hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + count)) | (code >> (5 - count)));
156-
}
157-
158-
if (insert) {
159-
_lfList.insert(_lfList.begin(), loadedLists.begin(), loadedLists.end());
160-
} else {
161-
_lfList.insert(_lfList.end(), loadedLists.begin(), loadedLists.end());
162-
}
163-
}
120+
void LoadLFListFromLineProvider(const std::function<bool(char*, size_t)>& getLine, bool insert = false);
164121
};
165122

166123
extern DeckManager deckManager;

gframe/game.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,6 @@ bool Game::Initialize() {
311311
wCreateHost->setVisible(false);
312312
env->addStaticText(dataManager.GetSysString(1226), irr::core::rect<irr::s32>(20, 30, 220, 50), false, false, wCreateHost);
313313
cbHostLFlist = env->addComboBox(irr::core::rect<irr::s32>(140, 25, 300, 50), wCreateHost);
314-
for(unsigned int i = 0; i < deckManager._lfList.size(); ++i)
315-
cbHostLFlist->addItem(deckManager._lfList[i].listName.c_str(), deckManager._lfList[i].hash);
316-
cbHostLFlist->setSelected(gameConf.use_lflist ? gameConf.default_lflist : cbHostLFlist->getItemCount() - 1);
317314
env->addStaticText(dataManager.GetSysString(1225), irr::core::rect<irr::s32>(20, 60, 220, 80), false, false, wCreateHost);
318315
cbRule = env->addComboBox(irr::core::rect<irr::s32>(140, 55, 300, 80), wCreateHost);
319316
cbRule->setMaxSelectionRows(10);
@@ -1551,6 +1548,10 @@ void Game::RefreshLFList() {
15511548
cbLFlist->addItem(deckManager._lfList[i].listName.c_str());
15521549
cbLFlist->setEnabled(gameConf.use_lflist);
15531550
cbLFlist->setSelected(gameConf.use_lflist ? gameConf.default_lflist : cbLFlist->getItemCount() - 1);
1551+
cbHostLFlist->clear();
1552+
for(unsigned int i = 0; i < deckManager._lfList.size(); ++i)
1553+
cbHostLFlist->addItem(deckManager._lfList[i].listName.c_str(), deckManager._lfList[i].hash);
1554+
cbHostLFlist->setSelected(gameConf.use_lflist ? gameConf.default_lflist : cbHostLFlist->getItemCount() - 1);
15541555
}
15551556
void Game::RefreshBot() {
15561557
if(!gameConf.enable_bot_mode)

0 commit comments

Comments
 (0)