Commit d4be967f authored by wind2009's avatar wind2009

Merge branch 'server' into server-develop

parents 16c5a77a 98b077cc
......@@ -437,8 +437,8 @@ jobs:
- name: Copy premake files
run: |
cp -r premake/* .
cp -r resource/* .
cp -pr premake/* .
cp -pr resource/* .
- name: Use premake to generate make files (apt packages)
if: matrix.static-link != true
......@@ -472,21 +472,15 @@ jobs:
fail-fast: false
matrix:
name:
- macos-13-intel
# - macos-13-arm-cross-compile-static-link
- macos-13-universal-static-link
- macos-15-intel
- macos-15-universal-static-link
- macos-15-arm
# - macos-15-intel-cross-compile-static-link
# - macos-15-universal-static-link
include:
- name: macos-13-intel
os: macos-13
# - name: macos-13-arm-cross-compile-static-link
# os: macos-13
# cross-build-arm: true
# static-link: true
- name: macos-13-universal-static-link
os: macos-13
- name: macos-15-intel
os: macos-15-intel
- name: macos-15-universal-static-link
os: macos-15
cross-build-intel: true
cross-build-arm: true
static-link: true
......@@ -495,11 +489,6 @@ jobs:
# - name: macos-15-intel-cross-compile-static-link
# os: macos-15
# cross-build-intel: true
# static-link: true
# - name: macos-15-universal-static-link
# os: macos-15
# cross-build-intel: true
# cross-build-arm: true
# static-link: true
runs-on: ${{ matrix.os }}
......@@ -664,8 +653,8 @@ jobs:
- name: Copy premake files
run: |
cp -r premake/* .
cp -r resource/* .
cp -pr premake/* .
cp -pr resource/* .
- name: Use premake to generate make files (Homebrew packages)
if: matrix.static-link != true
......
......@@ -3,6 +3,10 @@
/deck
/data
.DS_Store
/deck
/expansions
/fonts
/icon
......@@ -25,9 +29,10 @@
/ikpMP3.dll
/irrKlang.dll
/bin
/.vscode/
/bin/
/build
/obj
/obj/
/event
/freetype
/irrlicht
......
......@@ -93,7 +93,8 @@ mat_windows:
._exec_build:
stage: build
#variables:
variables:
GIT_STRATEGY: 'clone'
# NO_LUA_SAFE: '1' # on client no lua safe
#cache:
# key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
......
No preview for this file type
......@@ -27,13 +27,11 @@ ClientField::~ClientField() {
}
hand[i].clear();
for (auto& card : mzone[i]) {
if (card)
delete card;
delete card;
card = nullptr;
}
for (auto& card : szone[i]) {
if (card)
delete card;
delete card;
card = nullptr;
}
for (auto& card : grave[i]) {
......@@ -44,7 +42,6 @@ ClientField::~ClientField() {
delete card;
}
remove[i].clear();
for (auto& card : extra[i]) {
delete card;
}
......@@ -57,30 +54,33 @@ ClientField::~ClientField() {
}
void ClientField::Clear() {
for(int i = 0; i < 2; ++i) {
for(auto cit = deck[i].begin(); cit != deck[i].end(); ++cit)
delete *cit;
for (auto& card : deck[i]) {
delete card;
}
deck[i].clear();
for(auto cit = hand[i].begin(); cit != hand[i].end(); ++cit)
delete *cit;
for (auto& card : hand[i]) {
delete card;
}
hand[i].clear();
for(auto cit = mzone[i].begin(); cit != mzone[i].end(); ++cit) {
if(*cit)
delete *cit;
*cit = 0;
}
for(auto cit = szone[i].begin(); cit != szone[i].end(); ++cit) {
if(*cit)
delete *cit;
*cit = 0;
}
for(auto cit = grave[i].begin(); cit != grave[i].end(); ++cit)
delete *cit;
for (auto& card : mzone[i]) {
delete card;
card = nullptr;
}
for (auto& card : szone[i]) {
delete card;
card = nullptr;
}
for (auto& card : grave[i]) {
delete card;
}
grave[i].clear();
for(auto cit = remove[i].begin(); cit != remove[i].end(); ++cit)
delete *cit;
for (auto& card : remove[i]) {
delete card;
}
remove[i].clear();
for(auto cit = extra[i].begin(); cit != extra[i].end(); ++cit)
delete *cit;
for (auto& card : extra[i]) {
delete card;
}
extra[i].clear();
deck_act[i] = false;
grave_act[i] = false;
......@@ -88,8 +88,9 @@ void ClientField::Clear() {
extra_act[i] = false;
pzone_act[i] = false;
}
for(auto sit = overlay_cards.begin(); sit != overlay_cards.end(); ++sit)
delete *sit;
for (auto& card : overlay_cards) {
delete card;
}
overlay_cards.clear();
extra_p_count[0] = 0;
extra_p_count[1] = 0;
......@@ -417,7 +418,8 @@ void ClientField::ClearChainSelect() {
conti_act = false;
}
// needs to be synchronized with EGET_SCROLL_BAR_CHANGED
void ClientField::ShowSelectCard(bool buttonok, bool chain) {
void ClientField::ShowSelectCard(bool buttonok, bool is_continuous) {
select_continuous = is_continuous;
if(cant_check_grave) {
bool has_card_in_grave = false;
for (auto& pcard : selectable_cards) {
......@@ -444,7 +446,7 @@ void ClientField::ShowSelectCard(bool buttonok, bool chain) {
// image
if(selectable_cards[i]->code)
mainGame->imageLoading.insert(std::make_pair(mainGame->btnCardSelect[i], selectable_cards[i]->code));
else if(conti_selecting)
else if(select_continuous)
mainGame->imageLoading.insert(std::make_pair(mainGame->btnCardSelect[i], selectable_cards[i]->chain_code));
else
mainGame->btnCardSelect[i]->setImage(imageManager.tCover[selectable_cards[i]->controler + 2]);
......@@ -454,8 +456,8 @@ void ClientField::ShowSelectCard(bool buttonok, bool chain) {
if(mainGame->dInfo.curMsg != MSG_SORT_CARD) {
// text
wchar_t formatBuffer[2048];
if(conti_selecting)
myswprintf(formatBuffer, L"%ls", DataManager::unknown_string);
if(select_continuous)
myswprintf(formatBuffer, L"%ls", dataManager.unknown_string);
else if(cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE)
myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0));
else if(selectable_cards[i]->location == LOCATION_OVERLAY)
......@@ -470,7 +472,7 @@ void ClientField::ShowSelectCard(bool buttonok, bool chain) {
if (selectable_cards[i]->is_selected)
mainGame->stCardPos[i]->setBackgroundColor(0xffffff00);
else {
if(conti_selecting)
if(select_continuous)
mainGame->stCardPos[i]->setBackgroundColor(0xffffffff);
else if(selectable_cards[i]->location == LOCATION_OVERLAY) {
if(selectable_cards[i]->owner != selectable_cards[i]->overlayTarget->controler)
......@@ -1547,7 +1549,8 @@ void ClientField::UpdateDeclarableList() {
int trycode = BufferIO::GetVal(pname);
CardData cd;
if (dataManager.GetData(trycode, &cd) && is_declarable(cd, declare_opcodes)) {
auto it = dataManager.GetStringPointer(trycode);
auto& _strings = dataManager.GetStringTable();
auto it = _strings.find(trycode);
mainGame->lstANCard->clear();
ancard.clear();
mainGame->lstANCard->addItem(it->second.name.c_str());
......@@ -1560,19 +1563,23 @@ void ClientField::UpdateDeclarableList() {
}
mainGame->lstANCard->clear();
ancard.clear();
for(auto cit = dataManager.strings_begin(); cit != dataManager.strings_end(); ++cit) {
if(cit->second.name.find(pname) != std::wstring::npos) {
auto cp = dataManager.GetCodePointer(cit->first);
if (cp == dataManager.datas_end())
auto& _datas = dataManager.GetDataTable();
auto& _strings = dataManager.GetStringTable();
for(auto& entry : _strings) {
auto& code = entry.first;
auto& str = entry.second;
if(str.name.find(pname) != std::wstring::npos) {
auto cp = _datas.find(code);
if (cp == _datas.end())
continue;
//datas.alias can be double card names or alias
if(is_declarable(cp->second, declare_opcodes)) {
if(pname == cit->second.name || trycode == cit->first) { //exact match or last used
mainGame->lstANCard->insertItem(0, cit->second.name.c_str(), -1);
ancard.insert(ancard.begin(), cit->first);
if(pname == str.name || trycode == code) { //exact match or last used
mainGame->lstANCard->insertItem(0, str.name.c_str(), -1);
ancard.insert(ancard.begin(), code);
} else {
mainGame->lstANCard->addItem(cit->second.name.c_str());
ancard.push_back(cit->first);
mainGame->lstANCard->addItem(str.name.c_str());
ancard.push_back(code);
}
}
}
......
......@@ -86,14 +86,14 @@ public:
ChainInfo current_chain;
bool last_chain{ false };
bool deck_reversed{ false };
bool conti_selecting{ false };
bool select_continuous{ false };
bool cant_check_grave{ false };
bool tag_surrender{ false };
bool tag_teammate_surrender{ false };
std::mt19937 rnd;
ClientField();
~ClientField();
~ClientField() override;
void Clear();
void Initial(int player, int deckc, int extrac, int sidec = 0);
void ResetSequence(std::vector<ClientCard*>& list, bool reset_height);
......@@ -105,7 +105,7 @@ public:
void ClearCommandFlag();
void ClearSelect();
void ClearChainSelect();
void ShowSelectCard(bool buttonok = false, bool chain = false);
void ShowSelectCard(bool buttonok = false, bool is_continuous = false);
void ShowChainCard();
void ShowLocationCard();
void ShowSelectOption(int select_hint = 0);
......
......@@ -82,7 +82,7 @@ inline FILE* mywfopen(const wchar_t* filename, const char* mode) {
#include <irrlicht.h>
#endif
extern const unsigned short PRO_VERSION;
constexpr uint16_t PRO_VERSION = 0x1362;
extern unsigned int enable_log;
extern bool exit_on_return;
extern bool open_file;
......
......@@ -6,11 +6,7 @@
namespace ygo {
const wchar_t* DataManager::unknown_string = L"???";
unsigned char DataManager::scriptBuffer[0x100000] = {};
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
irr::io::IFileSystem* DataManager::FileSystem = nullptr;
#endif
DataManager dataManager;
DataManager::DataManager() : _datas(32768), _strings(32768) {
......@@ -328,7 +324,7 @@ std::wstring DataManager::FormatAttribute(unsigned int attribute) const {
if (attribute & (0x1U << i)) {
if (!buffer.empty())
buffer.push_back(L'|');
buffer.append(GetSysString(1010 + i));
buffer.append(GetSysString(STRING_ID_ATTRIBUTE + i));
}
}
if (buffer.empty())
......@@ -341,7 +337,7 @@ std::wstring DataManager::FormatRace(unsigned int race) const {
if(race & (0x1U << i)) {
if (!buffer.empty())
buffer.push_back(L'|');
buffer.append(GetSysString(1020 + i));
buffer.append(GetSysString(STRING_ID_RACE + i));
}
}
if (buffer.empty())
......@@ -350,12 +346,11 @@ std::wstring DataManager::FormatRace(unsigned int race) const {
}
std::wstring DataManager::FormatType(unsigned int type) const {
std::wstring buffer;
int i = 1050;
for (unsigned filter = TYPE_MONSTER; filter <= TYPE_LINK; filter <<= 1, ++i) {
if (type & filter) {
for (int i = 0; i < TYPES_COUNT; ++i) {
if (type & (0x1U << i)) {
if (!buffer.empty())
buffer.push_back(L'|');
buffer.append(GetSysString(i));
buffer.append(GetSysString(STRING_ID_TYPE + i));
}
}
if (buffer.empty())
......@@ -446,9 +441,9 @@ unsigned char* DataManager::ReadScriptFromIrrFS(const char* script_name, int* sl
#ifdef _WIN32
wchar_t fname[256]{};
BufferIO::DecodeUTF8(script_name, fname);
auto reader = FileSystem->createAndOpenFile(fname);
auto reader = dataManager.FileSystem->createAndOpenFile(fname);
#else
auto reader = FileSystem->createAndOpenFile(script_name);
auto reader = dataManager.FileSystem->createAndOpenFile(script_name);
#endif
if (!reader)
return nullptr;
......
......@@ -15,6 +15,7 @@ namespace irr {
}
namespace ygo {
constexpr int MAX_STRING_ID = 0x7ff;
constexpr uint32_t MIN_CARD_ID = (uint32_t)(MAX_STRING_ID + 1) >> 4;
constexpr uint32_t MAX_CARD_ID = 0x0fffffffU;
......@@ -71,19 +72,15 @@ public:
code_pointer GetCodePointer(uint32_t code) const;
#ifndef YGOPRO_SERVER_MODE
string_pointer GetStringPointer(uint32_t code) const;
code_pointer datas_begin() const noexcept {
return _datas.cbegin();
}
code_pointer datas_end() const noexcept {
return _datas.cend();
}
string_pointer strings_begin() const noexcept {
return _strings.cbegin();
#endif
const std::unordered_map<uint32_t, CardDataC>& GetDataTable() const {
return _datas;
}
string_pointer strings_end() const noexcept {
return _strings.cend();
#ifndef YGOPRO_SERVER_MODE
const std::unordered_map<uint32_t, CardString>& GetStringTable() const {
return _strings;
}
#endif //YGOPRO_SERVER_MODE
#endif
bool GetData(uint32_t code, CardData* pData) const;
#ifndef YGOPRO_SERVER_MODE
bool GetString(uint32_t code, CardString* pStr) const;
......@@ -109,9 +106,17 @@ public:
std::unordered_map<unsigned int, std::wstring> _sysStrings;
#endif
char errmsg[512]{};
const wchar_t* unknown_string{ L"???" };
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
irr::io::IFileSystem* FileSystem{};
#endif
static constexpr int STRING_ID_ATTRIBUTE = 1010;
static constexpr int STRING_ID_RACE = 1020;
static constexpr int STRING_ID_TYPE = 1050;
static constexpr int TYPES_COUNT = 27;
static unsigned char scriptBuffer[0x100000];
static const wchar_t* unknown_string;
static uint32_t CardReader(uint32_t, card_data*);
static unsigned char* ScriptReaderEx(const char* script_path, int* slen);
......@@ -121,10 +126,6 @@ public:
#endif
//read by fread
static unsigned char* ReadScriptFromFile(const char* script_name, int* slen);
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
static irr::io::IFileSystem* FileSystem;
#endif
#ifndef YGOPRO_SERVER_MODE
static bool deck_sort_lv(code_pointer l1, code_pointer l2);
......
......@@ -141,6 +141,7 @@ void DeckBuilder::Terminate() {
bool DeckBuilder::OnEvent(const irr::SEvent& event) {
if(mainGame->dField.OnCommonEvent(event))
return false;
auto& _datas = dataManager.GetDataTable();
switch(event.EventType) {
case irr::EET_GUI_EVENT: {
irr::s32 id = event.GUIEvent.Caller->getID();
......@@ -428,7 +429,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
mainGame->lstCategories->addItem(catename);
catesel = mainGame->lstCategories->getItemCount() - 1;
} else {
for(int i = 3; i < (int)mainGame->lstCategories->getItemCount(); i++) {
for(int i = DECK_CATEGORY_CUSTOM; i < (int)mainGame->lstCategories->getItemCount(); i++) {
if(!mywcsncasecmp(mainGame->lstCategories->getListItem(i), catename, 256)) {
catesel = i;
mainGame->stACMessage->setText(dataManager.GetSysString(1474));
......@@ -448,6 +449,8 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
}
case BUTTON_RENAME_CATEGORY: {
int catesel = mainGame->lstCategories->getSelected();
if (catesel < DECK_CATEGORY_CUSTOM)
break;
const wchar_t* oldcatename = mainGame->lstCategories->getListItem(catesel);
const wchar_t* newcatename = mainGame->ebDMName->getText();
if(DeckManager::RenameCategory(oldcatename, newcatename)) {
......@@ -458,7 +461,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
catesel = mainGame->lstCategories->getItemCount() - 1;
} else {
catesel = 0;
for(int i = 3; i < (int)mainGame->lstCategories->getItemCount(); i++) {
for(int i = DECK_CATEGORY_CUSTOM; i < (int)mainGame->lstCategories->getItemCount(); i++) {
if(!mywcsncasecmp(mainGame->lstCategories->getListItem(i), newcatename, 256)) {
catesel = i;
mainGame->stACMessage->setText(dataManager.GetSysString(1474));
......@@ -478,11 +481,13 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
}
case BUTTON_DELETE_CATEGORY: {
int catesel = mainGame->lstCategories->getSelected();
if (catesel < DECK_CATEGORY_CUSTOM)
break;
const wchar_t* catename = mainGame->lstCategories->getListItem(catesel);
if(DeckManager::DeleteCategory(catename)) {
mainGame->cbDBCategory->removeItem(catesel);
mainGame->lstCategories->removeItem(catesel);
catesel = 2;
catesel = DECK_CATEGORY_NONE;
mainGame->lstCategories->setSelected(catesel);
RefreshDeckList();
mainGame->lstDecks->setSelected(0);
......@@ -1074,8 +1079,8 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
break;
dragx = event.MouseInput.X;
dragy = event.MouseInput.Y;
draging_pointer = dataManager.GetCodePointer(hovered_code);
if(draging_pointer == dataManager.datas_end())
draging_pointer = _datas.find(hovered_code);
if (draging_pointer == _datas.end())
break;
if(hovered_pos == 4) {
if(!check_limit(draging_pointer))
......@@ -1128,8 +1133,8 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
break;
if(hovered_pos == 0 || hovered_seq == -1)
break;
auto pointer = dataManager.GetCodePointer(hovered_code);
if(pointer == dataManager.datas_end())
auto pointer = _datas.find(hovered_code);
if (pointer == _datas.end())
break;
soundManager.PlaySoundEffect(SOUND_CARD_DROP);
if(hovered_pos == 1) {
......@@ -1163,8 +1168,8 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
} else if(hovered_pos == 3) {
pop_side(hovered_seq);
} else {
auto pointer = dataManager.GetCodePointer(hovered_code);
if(pointer == dataManager.datas_end())
auto pointer = _datas.find(hovered_code);
if (pointer == _datas.end())
break;
if(!check_limit(pointer))
break;
......@@ -1198,8 +1203,8 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
break;
if (is_draging)
break;
auto pointer = dataManager.GetCodePointer(hovered_code);
if (pointer == dataManager.datas_end())
auto pointer = _datas.find(hovered_code);
if (pointer == _datas.end())
break;
if(!check_limit(pointer))
break;
......@@ -1468,10 +1473,13 @@ void DeckBuilder::FilterCards() {
query_elements.push_back(element);
}
}
for(code_pointer ptr = dataManager.datas_begin(); ptr != dataManager.datas_end(); ++ptr) {
const CardDataC& data = ptr->second;
auto strpointer = dataManager.GetStringPointer(ptr->first);
if (strpointer == dataManager.strings_end())
auto& _datas = dataManager.GetDataTable();
auto& _strings = dataManager.GetStringTable();
for (code_pointer ptr = _datas.begin(); ptr != _datas.end(); ++ptr) {
auto& code = ptr->first;
auto& data = ptr->second;
auto strpointer = _strings.find(code);
if (strpointer == _strings.end())
continue;
const CardString& strings = strpointer->second;
if(data.type & TYPE_TOKEN)
......@@ -1877,16 +1885,16 @@ bool DeckBuilder::check_limit(code_pointer pointer) {
auto flit = filterList->content.find(limitcode);
if(flit != filterList->content.end())
limit = flit->second;
for(auto it = deckManager.current_deck.main.begin(); it != deckManager.current_deck.main.end(); ++it) {
if((*it)->first == limitcode || (*it)->second.alias == limitcode)
for (auto& card : deckManager.current_deck.main) {
if (card->first == limitcode || card->second.alias == limitcode)
limit--;
}
for(auto it = deckManager.current_deck.extra.begin(); it != deckManager.current_deck.extra.end(); ++it) {
if((*it)->first == limitcode || (*it)->second.alias == limitcode)
for (auto& card : deckManager.current_deck.extra) {
if (card->first == limitcode || card->second.alias == limitcode)
limit--;
}
for(auto it = deckManager.current_deck.side.begin(); it != deckManager.current_deck.side.end(); ++it) {
if((*it)->first == limitcode || (*it)->second.alias == limitcode)
for (auto& card : deckManager.current_deck.side) {
if (card->first == limitcode || card->second.alias == limitcode)
limit--;
}
return limit > 0;
......
......@@ -5,9 +5,6 @@
namespace ygo {
#ifndef YGOPRO_SERVER_MODE
char DeckManager::deckBuffer[0x10000]{};
#endif
DeckManager deckManager;
void DeckManager::LoadLFListSingle(const char* path) {
......@@ -155,42 +152,46 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
uint32_t DeckManager::LoadDeck(Deck& deck, uint32_t dbuf[], int mainc, int sidec, bool is_packlist) {
deck.clear();
uint32_t errorcode = 0;
CardData cd;
auto& _datas = dataManager.GetDataTable();
for(int i = 0; i < mainc; ++i) {
auto code = dbuf[i];
if(!dataManager.GetData(code, &cd)) {
auto it = _datas.find(code);
if(it == _datas.end()) {
errorcode = code;
continue;
}
auto& cd = it->second;
if (cd.type & TYPE_TOKEN) {
errorcode = code;
continue;
}
if(is_packlist) {
deck.main.push_back(dataManager.GetCodePointer(code));
deck.main.push_back(it);
continue;
}
if (cd.type & TYPES_EXTRA_DECK) {
if (deck.extra.size() < EXTRA_MAX_SIZE)
deck.extra.push_back(dataManager.GetCodePointer(code));
deck.extra.push_back(it);
}
else {
if (deck.main.size() < DECK_MAX_SIZE)
deck.main.push_back(dataManager.GetCodePointer(code));
deck.main.push_back(it);
}
}
for(int i = 0; i < sidec; ++i) {
auto code = dbuf[mainc + i];
if(!dataManager.GetData(code, &cd)) {
auto it = _datas.find(code);
if(it == _datas.end()) {
errorcode = code;
continue;
}
auto& cd = it->second;
if (cd.type & TYPE_TOKEN) {
errorcode = code;
continue;
}
if(deck.side.size() < SIDE_MAX_SIZE)
deck.side.push_back(dataManager.GetCodePointer(code));
deck.side.push_back(it);
}
return errorcode;
}
......@@ -252,15 +253,15 @@ bool DeckManager::LoadSide(Deck& deck, uint32_t dbuf[], int mainc, int sidec) {
void DeckManager::GetCategoryPath(wchar_t* ret, int index, const wchar_t* text) {
wchar_t catepath[256];
switch(index) {
case 0:
case DECK_CATEGORY_PACK:
myswprintf(catepath, L"./pack");
break;
case 1:
case DECK_CATEGORY_BOT:
BufferIO::CopyWideString(mainGame->gameConf.bot_deck_path, catepath);
break;
case -1:
case 2:
case 3:
case DECK_CATEGORY_NONE:
case DECK_CATEGORY_SEPARATOR:
myswprintf(catepath, L"./deck");
break;
default:
......@@ -286,11 +287,11 @@ FILE* DeckManager::OpenDeckFile(const wchar_t* file, const char* mode) {
}
irr::io::IReadFile* DeckManager::OpenDeckReader(const wchar_t* file) {
#ifdef _WIN32
auto reader = DataManager::FileSystem->createAndOpenFile(file);
auto reader = dataManager.FileSystem->createAndOpenFile(file);
#else
char file2[256];
BufferIO::EncodeUTF8(file, file2);
auto reader = DataManager::FileSystem->createAndOpenFile(file2);
auto reader = dataManager.FileSystem->createAndOpenFile(file2);
#endif
return reader;
}
......@@ -300,6 +301,9 @@ bool DeckManager::LoadCurrentDeck(std::istringstream& deckStream, bool is_packli
}
bool DeckManager::LoadCurrentDeck(const wchar_t* file, bool is_packlist) {
current_deck.clear();
if (!file[0])
return false;
char deckBuffer[MAX_YDK_SIZE]{};
auto reader = OpenDeckReader(file);
if(!reader) {
wchar_t localfile[256];
......@@ -326,11 +330,12 @@ bool DeckManager::LoadCurrentDeck(const wchar_t* file, bool is_packlist) {
bool DeckManager::LoadCurrentDeck(int category_index, const wchar_t* category_name, const wchar_t* deckname) {
wchar_t filepath[256];
GetDeckFile(filepath, category_index, category_name, deckname);
bool is_packlist = (category_index == 0);
bool res = LoadCurrentDeck(filepath, is_packlist);
if (res && mainGame->is_building)
bool is_packlist = (category_index == DECK_CATEGORY_PACK);
if(!LoadCurrentDeck(filepath, is_packlist))
return false;
if (mainGame->is_building)
mainGame->deckBuilder.RefreshPackListScroll();
return res;
return true;
}
void DeckManager::SaveDeck(const Deck& deck, std::stringstream& deckStream) {
deckStream << "#created by ..." << std::endl;
......@@ -352,7 +357,7 @@ bool DeckManager::SaveDeck(const Deck& deck, const wchar_t* file) {
return false;
std::stringstream deckStream;
SaveDeck(deck, deckStream);
std::fwrite(deckStream.str().c_str(), 1, deckStream.str().length(), fp);
std::fputs(deckStream.str().c_str(), fp);
std::fclose(fp);
return true;
}
......
......@@ -23,14 +23,21 @@
#endif
namespace ygo {
constexpr int DECK_MAX_SIZE = YGOPRO_MAX_DECK;
constexpr int DECK_MIN_SIZE = YGOPRO_MIN_DECK;
constexpr int EXTRA_MAX_SIZE = YGOPRO_MAX_EXTRA;
constexpr int SIDE_MAX_SIZE = YGOPRO_MAX_SIDE;
constexpr int PACK_MAX_SIZE = 1000;
constexpr int MAINC_MAX = 250; // the limit of card_state
constexpr int SIDEC_MAX = MAINC_MAX;
constexpr int DECK_MAX_SIZE = YGOPRO_MAX_DECK;
constexpr int DECK_MIN_SIZE = YGOPRO_MIN_DECK;
constexpr int EXTRA_MAX_SIZE = YGOPRO_MAX_EXTRA;
constexpr int SIDE_MAX_SIZE = YGOPRO_MAX_SIDE;
constexpr int PACK_MAX_SIZE = 1000;
constexpr int MAINC_MAX = 250; // the limit of card_state
constexpr int SIDEC_MAX = MAINC_MAX;
constexpr int DECK_CATEGORY_PACK = 0;
constexpr int DECK_CATEGORY_BOT = 1;
constexpr int DECK_CATEGORY_NONE = 2;
constexpr int DECK_CATEGORY_SEPARATOR = 3;
constexpr int DECK_CATEGORY_CUSTOM = 4;
struct LFList {
unsigned int hash{};
......@@ -62,11 +69,13 @@ struct DeckArray {
class DeckManager {
public:
#ifndef YGOPRO_SERVER_MODE
Deck current_deck;
#endif
std::vector<LFList> _lfList;
#ifndef YGOPRO_SERVER_MODE
static char deckBuffer[0x10000];
static constexpr int MAX_YDK_SIZE = 0x10000;
#endif
void LoadLFListSingle(const char* path);
......
......@@ -1095,7 +1095,6 @@ void Game::HideElement(irr::gui::IGUIElement * win, bool set_action) {
if(win == wCardSelect) {
for(int i = 0; i < 5; ++i)
btnCardSelect[i]->setDrawImage(false);
dField.conti_selecting = false;
stCardListTip->setVisible(false);
for(auto& pcard : dField.selectable_cards)
dField.SetShowMark(pcard, false);
......@@ -1307,8 +1306,9 @@ void Game::DrawDeckBd() {
else
myswprintf(adBuffer, L"%d/-", ptr->second.attack);
}
myswprintf(textBuffer, L"%ls/%ls %ls%d", dataManager.FormatAttribute(ptr->second.attribute).c_str(), dataManager.FormatRace(ptr->second.race).c_str(),
form, ptr->second.level);
const auto& attribute = dataManager.FormatAttribute(ptr->second.attribute);
const auto& race = dataManager.FormatRace(ptr->second.race);
myswprintf(textBuffer, L"%ls/%ls %ls%d", attribute.c_str(), race.c_str(), form, ptr->second.level);
DrawShadowText(textFont, textBuffer, Resize(860, 187 + i * 66, 955, 207 + i * 66), Resize(1, 1, 0, 0));
if(ptr->second.type & TYPE_PENDULUM) {
myswprintf(scaleBuffer, L" %d/%d", ptr->second.lscale, ptr->second.rscale);
......@@ -1318,7 +1318,8 @@ void Game::DrawDeckBd() {
} else {
myswprintf(textBuffer, L"%ls", dataManager.GetName(ptr->first));
DrawShadowText(textFont, textBuffer, Resize(860, 165 + i * 66, 955, 185 + i * 66), Resize(1, 1, 0, 0));
myswprintf(textBuffer, L"%ls", dataManager.FormatType(ptr->second.type).c_str());
const auto& type = dataManager.FormatType(ptr->second.type);
myswprintf(textBuffer, L"%ls", type.c_str());
DrawShadowText(textFont, textBuffer, Resize(860, 187 + i * 66, 955, 207 + i * 66), Resize(1, 1, 0, 0));
myswprintf(textBuffer, L"%ls", availBuffer);
DrawShadowText(textFont, textBuffer, Resize(860, 209 + i * 66, 955, 229 + i * 66), Resize(1, 1, 0, 0));
......
......@@ -762,8 +762,11 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) {
prep += sizeof new_replay.pheader;
std::memcpy(new_replay.comp_data, prep, len - sizeof new_replay.pheader - 1);
new_replay.comp_size = len - sizeof new_replay.pheader - 1;
if(mainGame->actionParam)
new_replay.SaveReplay(mainGame->ebRSName->getText());
if (mainGame->actionParam) {
bool save_result = new_replay.SaveReplay(mainGame->ebRSName->getText());
if (!save_result)
new_replay.SaveReplay(L"_LastReplay");
}
else
new_replay.SaveReplay(L"_LastReplay");
}
......@@ -1113,7 +1116,8 @@ bool DuelClient::ClientAnalyze(unsigned char* msg, int len) {
break;
}
case HINT_RACE: {
myswprintf(textBuffer, dataManager.GetSysString(1511), dataManager.FormatRace(data).c_str());
const auto& race = dataManager.FormatRace(data);
myswprintf(textBuffer, dataManager.GetSysString(1511), race.c_str());
mainGame->AddLog(textBuffer);
mainGame->gMutex.lock();
mainGame->SetStaticText(mainGame->stACMessage, 310, mainGame->guiFont, textBuffer);
......@@ -1123,7 +1127,8 @@ bool DuelClient::ClientAnalyze(unsigned char* msg, int len) {
break;
}
case HINT_ATTRIB: {
myswprintf(textBuffer, dataManager.GetSysString(1511), dataManager.FormatAttribute(data).c_str());
const auto& attribute = dataManager.FormatAttribute(data);
myswprintf(textBuffer, dataManager.GetSysString(1511), attribute.c_str());
mainGame->AddLog(textBuffer);
mainGame->gMutex.lock();
mainGame->SetStaticText(mainGame->stACMessage, 310, mainGame->guiFont, textBuffer);
......
......@@ -404,7 +404,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
}
} else {
selectable_cards.clear();
conti_selecting = false;
bool is_continuous = false;
switch(command_location) {
case LOCATION_DECK: {
for(size_t i = 0; i < deck[command_controler].size(); ++i)
......@@ -431,15 +431,15 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
break;
}
case POSITION_HINT: {
is_continuous = true;
selectable_cards = conti_cards;
std::sort(selectable_cards.begin(), selectable_cards.end());
auto eit = std::unique(selectable_cards.begin(), selectable_cards.end());
selectable_cards.erase(eit, selectable_cards.end());
conti_selecting = true;
break;
}
}
if(!conti_selecting) {
if (!is_continuous) {
mainGame->wCardSelect->setText(dataManager.GetSysString(566));
list_command = COMMAND_ACTIVATE;
} else {
......@@ -447,7 +447,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
list_command = COMMAND_OPERATION;
}
std::sort(selectable_cards.begin(), selectable_cards.end(), ClientCard::client_card_sort);
ShowSelectCard(true, true);
ShowSelectCard(true, is_continuous);
}
break;
}
......@@ -892,7 +892,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
// image
if(selectable_cards[i + pos]->code)
mainGame->btnCardSelect[i]->setImage(imageManager.GetTexture(selectable_cards[i + pos]->code));
else if(conti_selecting)
else if(select_continuous)
mainGame->btnCardSelect[i]->setImage(imageManager.GetTexture(selectable_cards[i + pos]->chain_code));
else
mainGame->btnCardSelect[i]->setImage(imageManager.tCover[selectable_cards[i + pos]->controler + 2]);
......@@ -905,8 +905,8 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
else
myswprintf(formatBuffer, L"");
} else {
if(conti_selecting)
myswprintf(formatBuffer, L"%ls", DataManager::unknown_string);
if(select_continuous)
myswprintf(formatBuffer, L"%ls", dataManager.unknown_string);
else if(cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE)
myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0));
else if(selectable_cards[i + pos]->location == LOCATION_OVERLAY)
......@@ -919,7 +919,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
}
mainGame->stCardPos[i]->setText(formatBuffer);
// color
if(conti_selecting)
if(select_continuous)
mainGame->stCardPos[i]->setBackgroundColor(0xffffffff);
else if(selectable_cards[i + pos]->location == LOCATION_OVERLAY) {
if(selectable_cards[i + pos]->owner != selectable_cards[i + pos]->overlayTarget->controler)
......@@ -1597,7 +1597,9 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
myswprintf(formatBuffer, L"\nLINK-%d", mcard->link);
str.append(formatBuffer);
}
myswprintf(formatBuffer, L" %ls/%ls", dataManager.FormatRace(mcard->race).c_str(), dataManager.FormatAttribute(mcard->attribute).c_str());
const auto& race = dataManager.FormatRace(mcard->race);
const auto& attribute = dataManager.FormatAttribute(mcard->attribute);
myswprintf(formatBuffer, L" %ls/%ls", race.c_str(), attribute.c_str());
str.append(formatBuffer);
if(mcard->location == LOCATION_HAND && (mcard->type & TYPE_PENDULUM)) {
myswprintf(formatBuffer, L"\n%d/%d", mcard->lscale, mcard->rscale);
......@@ -1622,10 +1624,14 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
myswprintf(formatBuffer, L"\n%ls%d", dataManager.GetSysString(211), mcard->chValue);
else if(mcard->cHint == CHINT_CARD)
myswprintf(formatBuffer, L"\n%ls%ls", dataManager.GetSysString(212), dataManager.GetName(mcard->chValue));
else if(mcard->cHint == CHINT_RACE)
myswprintf(formatBuffer, L"\n%ls%ls", dataManager.GetSysString(213), dataManager.FormatRace(mcard->chValue).c_str());
else if(mcard->cHint == CHINT_ATTRIBUTE)
myswprintf(formatBuffer, L"\n%ls%ls", dataManager.GetSysString(214), dataManager.FormatAttribute(mcard->chValue).c_str());
else if(mcard->cHint == CHINT_RACE) {
const auto& race = dataManager.FormatRace(mcard->chValue);
myswprintf(formatBuffer, L"\n%ls%ls", dataManager.GetSysString(213), race.c_str());
}
else if(mcard->cHint == CHINT_ATTRIBUTE) {
const auto& attribute = dataManager.FormatAttribute(mcard->chValue);
myswprintf(formatBuffer, L"\n%ls%ls", dataManager.GetSysString(214), attribute.c_str());
}
else if(mcard->cHint == CHINT_NUMBER)
myswprintf(formatBuffer, L"\n%ls%d", dataManager.GetSysString(215), mcard->chValue);
str.append(formatBuffer);
......
This diff is collapsed.
......@@ -26,16 +26,16 @@
#include <mutex>
#include <functional>
namespace ygo {
#ifndef YGOPRO_DEFAULT_DUEL_RULE
#define YGOPRO_DEFAULT_DUEL_RULE 5
constexpr int DEFAULT_DUEL_RULE = CURRENT_RULE;
#else
constexpr int DEFAULT_DUEL_RULE = YGOPRO_DEFAULT_DUEL_RULE;
#endif
#define DEFAULT_DUEL_RULE YGOPRO_DEFAULT_DUEL_RULE
constexpr int CONFIG_LINE_SIZE = 1024;
constexpr int TEXT_LINE_SIZE = 256;
namespace ygo {
template<size_t N>
bool IsExtension(const wchar_t* filename, const wchar_t(&extension)[N]) {
auto flen = std::wcslen(filename);
......
......@@ -87,7 +87,7 @@ int main(int argc, char* argv[]) {
ygo::game_info.draw_count = 1;
ygo::game_info.no_check_deck = false;
ygo::game_info.no_shuffle_deck = false;
ygo::game_info.duel_rule = DEFAULT_DUEL_RULE;
ygo::game_info.duel_rule = ygo::DEFAULT_DUEL_RULE;
ygo::game_info.time_limit = 180;
std::memset(ygo::pre_seed, 0, sizeof(ygo::pre_seed));
std::memset(ygo::pre_seed_specified, 0, sizeof(ygo::pre_seed_specified));
......@@ -103,15 +103,15 @@ int main(int argc, char* argv[]) {
mode = 0;
ygo::game_info.mode = mode;
if(argv[5][0] == 'T')
ygo::game_info.duel_rule = DEFAULT_DUEL_RULE - 1;
ygo::game_info.duel_rule = ygo::DEFAULT_DUEL_RULE - 1;
else if(argv[5][0] == 'F')
ygo::game_info.duel_rule = DEFAULT_DUEL_RULE;
ygo::game_info.duel_rule = ygo::DEFAULT_DUEL_RULE;
else {
int master_rule = atoi(argv[5]);
if(master_rule)
ygo::game_info.duel_rule = master_rule;
else
ygo::game_info.duel_rule = DEFAULT_DUEL_RULE;
ygo::game_info.duel_rule = ygo::DEFAULT_DUEL_RULE;
}
if(argv[6][0] == 'T')
ygo::game_info.no_check_deck = true;
......
......@@ -487,7 +487,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
if(prev_operation == BUTTON_RENAME_REPLAY) {
wchar_t newname[256];
BufferIO::CopyWideString(mainGame->ebRSName->getText(), newname);
if(mywcsncasecmp(newname + std::wcslen(newname) - 4, L".yrp", 4)) {
if (!IsExtension(newname, L".yrp")) {
myswprintf(newname, L"%ls.yrp", mainGame->ebRSName->getText());
}
if(Replay::RenameReplay(mainGame->lstReplayList->getListItem(prev_sel), newname)) {
......
......@@ -21,7 +21,7 @@ class FileSystem {
public:
static void SafeFileName(wchar_t* wfile) {
while((wfile = std::wcspbrk(wfile, L"<>:\"/\\|?*")) != nullptr)
*wfile++ = '_';
*wfile++ = L'_';
}
static bool IsFileExists(const wchar_t* wfile) {
......@@ -125,7 +125,7 @@ class FileSystem {
public:
static void SafeFileName(wchar_t* wfile) {
while((wfile = std::wcspbrk(wfile, L"/")) != nullptr)
*wfile++ = '_';
*wfile++ = L'_';
}
static bool IsFileExists(const char* file) {
......
......@@ -14,8 +14,9 @@
#define check_trivially_copyable(T) static_assert(std::is_trivially_copyable<T>::value == true && std::is_standard_layout<T>::value == true, "not trivially copyable")
namespace ygo {
constexpr int SIZE_NETWORK_BUFFER = 0x20000;
constexpr int MAX_DATA_SIZE = UINT16_MAX - 1;
constexpr int SIZE_NETWORK_BUFFER = 0x20000;
constexpr int MAX_DATA_SIZE = UINT16_MAX - 1;
struct HostInfo {
uint32_t lflist{};
......
......@@ -98,24 +98,30 @@ void Replay::EndRecord() {
}
is_recording = false;
}
void Replay::SaveReplay(const wchar_t* name) {
bool Replay::SaveReplay(const wchar_t* base_name) {
if(!FileSystem::IsDirExists(L"./replay") && !FileSystem::MakeDir(L"./replay"))
return;
wchar_t fname[256];
myswprintf(fname, L"./replay/%ls.yrp", name);
FILE* rfp = mywfopen(fname, "wb");
return false;
wchar_t filename[256]{};
wchar_t path[256]{};
BufferIO::CopyWideString(base_name, filename);
FileSystem::SafeFileName(filename);
if (myswprintf(path, L"./replay/%ls.yrp", filename) <= 0)
return false;
FILE* rfp = mywfopen(path, "wb");
if(!rfp)
return;
return false;
std::fwrite(&pheader, sizeof pheader, 1, rfp);
std::fwrite(comp_data, comp_size, 1, rfp);
std::fclose(rfp);
return true;
}
#ifndef YGOPRO_SERVER_MODE
bool Replay::OpenReplay(const wchar_t* name) {
FILE* rfp = mywfopen(name, "rb");
if(!rfp) {
wchar_t fname[256];
myswprintf(fname, L"./replay/%ls", name);
if (myswprintf(fname, L"./replay/%ls", name) <= 0)
return false;
rfp = mywfopen(fname, "rb");
}
if(!rfp)
......@@ -167,19 +173,28 @@ bool Replay::OpenReplay(const wchar_t* name) {
return true;
}
bool Replay::DeleteReplay(const wchar_t* name) {
if (std::wcschr(name, L'/') || std::wcschr(name, L'\\'))
return false;
wchar_t fname[256];
myswprintf(fname, L"./replay/%ls", name);
if(myswprintf(fname, L"./replay/%ls", name) <= 0)
return false;
return FileSystem::RemoveFile(fname);
}
bool Replay::RenameReplay(const wchar_t* oldname, const wchar_t* newname) {
wchar_t oldfname[256];
wchar_t newfname[256];
myswprintf(oldfname, L"./replay/%ls", oldname);
myswprintf(newfname, L"./replay/%ls", newname);
wchar_t old_path[256];
wchar_t new_path[256];
if (std::wcschr(oldname, L'/') || std::wcschr(oldname, L'\\'))
return false;
if (std::wcschr(newname, L'/') || std::wcschr(newname, L'\\'))
return false;
if (myswprintf(old_path, L"./replay/%ls", oldname) <= 0)
return false;
if (myswprintf(new_path, L"./replay/%ls", newname) <= 0)
return false;
char oldfilefn[1024];
char newfilefn[1024];
BufferIO::EncodeUTF8(oldfname, oldfilefn);
BufferIO::EncodeUTF8(newfname, newfilefn);
BufferIO::EncodeUTF8(old_path, oldfilefn);
BufferIO::EncodeUTF8(new_path, newfilefn);
int result = std::rename(oldfilefn, newfilefn);
return result == 0;
}
......
......@@ -71,7 +71,7 @@ public:
void WriteInt32(int32_t data, bool flush = true);
void Flush();
void EndRecord();
void SaveReplay(const wchar_t* name);
bool SaveReplay(const wchar_t* base_name);
// play
static bool DeleteReplay(const wchar_t* name);
......
This diff is collapsed.
Subproject commit efcf37aa269c17a60eb260a54bf8a837d2267265
Subproject commit 682ffa3c2db0443fd3afb725a1089a33077b1dc7
Subproject commit 68cf0aecab0d2c97f65186ba8ca7c072cf630a90
Subproject commit bb696eb5dc009d4b708bc9f85a29fd46fd6577cf
......@@ -669,6 +669,8 @@
!counter 0x6e 四季指示物
!counter 0x6f 龋齿指示物
!counter 0x70 盘子指示物
!counter 0x71 纠罪指示物
!counter 0x1072 少女指示物
#setnames, using tab for comment
!setname 0x1 正义盟军 AOJ
!setname 0x2 次世代 ジェネクス
......@@ -1238,7 +1240,7 @@
!setname 0x1b4 时空 タキオン
!setname 0x1b5 蓝泪 青い涙
!setname 0x1b6 石版
!setname 0x1b7 拟箱掳尸 Mimighoul
!setname 0x1b7 迷拟宝箱鬼 ミミグル
!setname 0x1b8 鲨 シャーク
!setname 0x11b8 鲨龙兽 シャーク・ドレイク
!setname 0x1b9 原石
......@@ -1251,12 +1253,12 @@
!setname 0x1c0 龙华 竜華
!setname 0x1c1 阿尔戈☆群星 ARGS
!setname 0x1c2 喷水引擎 アクア・ジェット
!setname 0x1c3 巳剑 Mitsurugi
!setname 0x1c3 巳剑 巳剣
!setname 0x1c4 征龙 征竜
!setname 0x1c5 再世 リジェネシス
!setname 0x1c6 统王 ドミナス
!setname 0x1c7 塞勒凯特 Serket
!setname 0x1c8 阿匹卜 Apophis
!setname 0x1c7 塞勒凯特 セルケト
!setname 0x1c8 阿匹卜 アポピス
!setname 0x1c9 星辰 ドラゴンテイル
!setname 0x1ca 味美喵 ヤミー
!setname 0x1cb K9
......@@ -1267,3 +1269,7 @@
!setname 0x1d0 死伟王 死偉王
!setname 0x1d1 绚岚 絢嵐
!setname 0x1d2 终刻 ドゥームズ
!setname 0x1d3 不可见之手 ヘカトンケイル
!setname 0x1d4 纠罪巧 糾罪巧
!setname 0x1d5 杀手级调整曲 キラーチューン
!setname 0x1d6 树熊 コアラ
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