Commit 9b8ad166 authored by nanahira's avatar nanahira

Merge branch 'develop' into server-develop

parents 6f28e7b0 42772b77
......@@ -3,8 +3,8 @@ set -x
set -o errexit
# ygopro-database
apt update && apt -y install wget git libarchive-tools
git clone --depth=1 https://code.mycard.moe/nanahira/ygopro-database
git clone --depth=1 https://code.moenext.com/nanahira/ygopro-database
cp -rf ./ygopro-database/locales/$TARGET_LOCALE/* .
# ygopro-images
mkdir pics
wget -O - https://cdn01.moecube.com/images/ygopro-images-${TARGET_LOCALE}.zip | bsdtar -C pics -xf -
wget -O - https://cdn02.moecube.com:444/images/ygopro-images-${TARGET_LOCALE}.zip | bsdtar -C pics -xf -
......@@ -6,8 +6,6 @@ TARGET_PLATFORM=$(arch)
TARGET_YGOPRO_BINARY_PATH=./ygopro-platforms/ygopro-platform-$TARGET_PLATFORM
export EVENT_INCLUDE_DIR=$PWD/libevent-stable/include
export EVENT_LIB_DIR=$PWD/libevent-stable/lib
export IRRLICHT_INCLUDE_DIR=$PWD/irrlicht/include
export IRRLICHT_LIB_DIR=$PWD/irrlicht/lib/$(arch)
export OPUS_INCLUDE_DIR=$PWD/miniaudio/external-built/include/opus
export OPUS_LIB_DIR=$PWD/miniaudio/external-built/lib
export VORBIS_INCLUDE_DIR=$PWD/miniaudio/external-built/include
......
......@@ -8,7 +8,7 @@ if [ -d "libevent-stable" ]; then
fi
if [ ! -d "libevent-2.0.22-stable" ]; then
wget -O - https://cdn01.moecube.com/ygopro-build-materials/libevent-2.0.22-stable.tar.gz | tar zfx -
wget -O - https://cdn02.moecube.com:444/ygopro-build-materials/libevent-2.0.22-stable.tar.gz | tar zfx -
fi
install_path="$PWD/libevent-stable"
......
#!/bin/bash
set -x
set -o errexit
IRRLICHT_REPO_URL="https://code.moenext.com/mycard/irrlicht-new.git"
IRRLICHT_BRANCH_NAME="master"
# if $CI_COMMIT_REF_NAME includes develop or pre, then we use the develop branch
if [[ "$CI_COMMIT_REF_NAME" == *"develop"* || "$CI_COMMIT_REF_NAME" == *".pre"* ]]; then
IRRLICHT_BRANCH_NAME="develop"
fi
if [ ! -d "irrlicht" ]; then
git clone --depth=1 --branch "$IRRLICHT_BRANCH_NAME" "$IRRLICHT_REPO_URL" irrlicht
else
cd irrlicht
git fetch origin "$IRRLICHT_BRANCH_NAME"
git checkout "$IRRLICHT_BRANCH_NAME"
git reset --hard origin/"$IRRLICHT_BRANCH_NAME"
cd ..
fi
......@@ -33,9 +33,13 @@ runForDepot() {
echo "$result" | jq .
}
runForDepot win32 zh-CN
runForDepot linux zh-CN
runForDepot darwin zh-CN
runForDepot win32 en-US
runForDepot linux en-US
runForDepot darwin en-US
if [[ "$CI_COMMIT_TAG" == *".pre"* ]]; then
echo "This is a pre-release, skipping upload."
else
runForDepot win32 zh-CN
runForDepot linux zh-CN
runForDepot darwin zh-CN
runForDepot win32 en-US
runForDepot linux en-US
runForDepot darwin en-US
fi
......@@ -401,12 +401,6 @@ jobs:
run: |
git clone --depth=1 https://github.com/mercury233/irrlicht
- name: Build irrlicht
run: |
cd irrlicht/source/Irrlicht/MacOSX
xcodebuild -project MacOSX.xcodeproj
cd ../../../..
- name: Copy premake files
run: |
cp -r premake/* .
......@@ -418,9 +412,7 @@ jobs:
./premake5 gmake \
--cc=clang \
--freetype-include-dir="/usr/local/include/freetype2" \
--opus-include-dir="/usr/local/include/opus" \
--irrlicht-include-dir="../irrlicht/include" \
--irrlicht-lib-dir="../irrlicht/source/Irrlicht/MacOSX/build/Release"
--opus-include-dir="/usr/local/include/opus"
- name: Use premake to generate make files (ARM64)
if: runner.arch == 'ARM64'
......@@ -438,9 +430,7 @@ jobs:
--opus-include-dir="/opt/homebrew/include/opus" \
--opus-lib-dir="/opt/homebrew/lib" \
--vorbis-include-dir="/opt/homebrew/include" \
--vorbis-lib-dir="/opt/homebrew/lib" \
--irrlicht-include-dir="../irrlicht/include" \
--irrlicht-lib-dir="../irrlicht/source/Irrlicht/MacOSX/build/Release"
--vorbis-lib-dir="/opt/homebrew/lib"
- name: Make
run: |
......
......@@ -14,14 +14,16 @@ mat_common:
- linux
script:
# lua
- wget -O - https://cdn01.moecube.com/ygopro-build-materials/lua-5.4.4.tar.gz | tar zfx -
- wget -O - https://cdn02.moecube.com:444/ygopro-build-materials/lua-5.4.4.tar.gz | tar zfx -
- mv lua-5.4.4 lua
# sqlite3
- wget -O - https://cdn01.moecube.com/ygopro-build-materials/sqlite-autoconf-3390300.tar.gz | tar zfx -
- wget -O - https://cdn02.moecube.com:444/ygopro-build-materials/sqlite-autoconf-3390300.tar.gz | tar zfx -
- mv sqlite-autoconf-3390300 sqlite3
# freetype
#- wget -O - https://cdn01.moecube.com/ygopro-build-materials/freetype-2.11.1.tar.gz | tar zfx -
#- wget -O - https://cdn02.moecube.com:444/ygopro-build-materials/freetype-2.11.1.tar.gz | tar zfx -
#- mv freetype-2.11.1 freetype
# irrlicht
- ./.ci/prepare-irrlicht.sh
# miniaudio
#- ./.ci/prepare-miniaudio.sh
# premake
......@@ -31,6 +33,7 @@ mat_common:
- lua
#- freetype
- sqlite3
- irrlicht
#- miniaudio
mat_submodules:
......@@ -47,31 +50,29 @@ mat_submodules:
- ocgcore
- script
mat_linux:
stage: prepare
tags:
- linux
image: git-registry.mycard.moe/mycard/docker-runner-base:debian11
script:
- apt update; apt -y install git wget tar
- git clone --depth=1 https://code.mycard.moe/mycard/irrlicht-new irrlicht
artifacts:
paths:
- irrlicht
#mat_linux:
# stage: prepare
# tags:
# - linux
# image: git-registry.mycard.moe/mycard/docker-runner-base:debian11
# script:
# - apt update; apt -y install git wget tar
# - ./.ci/prepare-irrlicht.sh
# artifacts:
# paths:
# - irrlicht
mat_macos:
stage: prepare
tags:
- linux
script:
- apt update; apt -y install wget tar git
- wget -O - https://cdn01.moecube.com/ygopro-build-materials/premake-5.0.0-beta5-macosx.tar.gz | tar zfx -
- apt update; apt -y install wget tar
- wget -O - https://cdn02.moecube.com:444/ygopro-build-materials/premake-5.0.0-beta5-macosx.tar.gz | tar zfx -
- chmod +x premake5
- git clone --depth=1 https://code.mycard.moe/mycard/irrlicht-new irrlicht
artifacts:
paths:
- premake5
- irrlicht
mat_windows:
stage: prepare
......@@ -80,18 +81,15 @@ mat_windows:
script:
- apt update; apt -y install wget tar patch p7zip-full
# premake5.exe
- wget https://cdn01.moecube.com/ygopro-build-materials/premake-5.0.0-beta5-windows.zip
- wget https://cdn02.moecube.com:444/ygopro-build-materials/premake-5.0.0-beta5-windows.zip
- 7z x -y premake-5.0.0-beta5-windows.zip
# event
- wget -O - https://cdn01.moecube.com/ygopro-build-materials/libevent-2.0.22-stable.tar.gz | tar zfx -
- wget -O - https://cdn02.moecube.com:444/ygopro-build-materials/libevent-2.0.22-stable.tar.gz | tar zfx -
- mv libevent-2.0.22-stable event
# irrlicht
- git clone --depth=1 https://code.mycard.moe/mycard/irrlicht-new irrlicht
artifacts:
paths:
- premake5.exe
- event
- irrlicht
._exec_build:
stage: build
......@@ -163,7 +161,7 @@ exec_windows_pro3:
image: git-registry.moenext.com/mycard/docker-ygopro-builder
dependencies:
- mat_common
- mat_linux
#- mat_linux
- mat_submodules
.exec_linux:
......
......@@ -47,7 +47,7 @@ static inline bool havePopupWindow() {
}
static inline void get_deck_file(wchar_t* ret) {
deckManager.GetDeckFile(ret, mainGame->cbDBCategory->getSelected(), mainGame->cbDBCategory->getText(), mainGame->cbDBDecks->getText());
DeckManager::GetDeckFile(ret, mainGame->cbDBCategory->getSelected(), mainGame->cbDBCategory->getText(), mainGame->cbDBDecks->getText());
}
static inline void load_current_deck(irr::gui::IGUIComboBox* cbCategory, irr::gui::IGUIComboBox* cbDeck) {
......@@ -185,7 +185,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
break;
wchar_t filepath[256];
get_deck_file(filepath);
if(deckManager.SaveDeck(deckManager.current_deck, filepath)) {
if(DeckManager::SaveDeck(deckManager.current_deck, filepath)) {
mainGame->stACMessage->setText(dataManager.GetSysString(1335));
mainGame->PopupElement(mainGame->wACMessage, 20);
is_modified = false;
......@@ -211,10 +211,10 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
}
int catesel = mainGame->cbDBCategory->getSelected();
wchar_t catepath[256];
deckManager.GetCategoryPath(catepath, catesel, mainGame->cbDBCategory->getText());
DeckManager::GetCategoryPath(catepath, catesel, mainGame->cbDBCategory->getText());
wchar_t filepath[256];
myswprintf(filepath, L"%ls/%ls.ydk", catepath, dname);
if(deckManager.SaveDeck(deckManager.current_deck, filepath)) {
if(DeckManager::SaveDeck(deckManager.current_deck, filepath)) {
mainGame->stACMessage->setText(dataManager.GetSysString(1335));
mainGame->PopupElement(mainGame->wACMessage, 20);
is_modified = false;
......@@ -437,7 +437,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
case BUTTON_NEW_CATEGORY: {
int catesel = 0;
const wchar_t* catename = mainGame->ebDMName->getText();
if(deckManager.CreateCategory(catename)) {
if(DeckManager::CreateCategory(catename)) {
mainGame->cbDBCategory->addItem(catename);
mainGame->lstCategories->addItem(catename);
catesel = mainGame->lstCategories->getItemCount() - 1;
......@@ -464,7 +464,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
int catesel = mainGame->lstCategories->getSelected();
const wchar_t* oldcatename = mainGame->lstCategories->getListItem(catesel);
const wchar_t* newcatename = mainGame->ebDMName->getText();
if(deckManager.RenameCategory(oldcatename, newcatename)) {
if(DeckManager::RenameCategory(oldcatename, newcatename)) {
mainGame->cbDBCategory->removeItem(catesel);
mainGame->cbDBCategory->addItem(newcatename);
mainGame->lstCategories->removeItem(catesel);
......@@ -493,7 +493,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
case BUTTON_DELETE_CATEGORY: {
int catesel = mainGame->lstCategories->getSelected();
const wchar_t* catename = mainGame->lstCategories->getListItem(catesel);
if(deckManager.DeleteCategory(catename)) {
if(DeckManager::DeleteCategory(catename)) {
mainGame->cbDBCategory->removeItem(catesel);
mainGame->lstCategories->removeItem(catesel);
catesel = 2;
......@@ -511,7 +511,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
case BUTTON_NEW_DECK: {
const wchar_t* deckname = mainGame->ebDMName->getText();
wchar_t catepath[256];
deckManager.GetCategoryPath(catepath, mainGame->cbDBCategory->getSelected(), mainGame->cbDBCategory->getText());
DeckManager::GetCategoryPath(catepath, mainGame->cbDBCategory->getSelected(), mainGame->cbDBCategory->getText());
wchar_t filepath[256];
myswprintf(filepath, L"%ls/%ls.ydk", catepath, deckname);
bool res = false;
......@@ -519,7 +519,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
deckManager.current_deck.main.clear();
deckManager.current_deck.extra.clear();
deckManager.current_deck.side.clear();
res = deckManager.SaveDeck(deckManager.current_deck, filepath);
res = DeckManager::SaveDeck(deckManager.current_deck, filepath);
RefreshDeckList();
ChangeCategory(mainGame->lstCategories->getSelected());
}
......@@ -576,7 +576,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
int decksel = mainGame->lstDecks->getSelected();
wchar_t filepath[256];
get_deck_file(filepath);
if(deckManager.DeleteDeck(filepath)) {
if(DeckManager::DeleteDeck(filepath)) {
mainGame->lstDecks->removeItem(decksel);
mainGame->cbDBDecks->removeItem(decksel);
decksel--;
......@@ -652,7 +652,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
}
bool res = false;
if(!FileSystem::IsFileExists(newfilepath)) {
res = deckManager.SaveDeck(deckManager.current_deck, newfilepath);
res = DeckManager::SaveDeck(deckManager.current_deck, newfilepath);
}
mainGame->lstCategories->setSelected(newcatename);
int catesel = mainGame->lstCategories->getSelected();
......@@ -753,7 +753,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
mainGame->cbDBDecks->setSelected(sel);
wchar_t filepath[256];
get_deck_file(filepath);
if(deckManager.DeleteDeck(filepath)) {
if(DeckManager::DeleteDeck(filepath)) {
mainGame->cbDBDecks->removeItem(sel);
int count = mainGame->cbDBDecks->getItemCount();
if(sel >= count)
......@@ -1048,7 +1048,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
break;
wchar_t filepath[256];
wchar_t catepath[256];
deckManager.GetCategoryPath(catepath, mainGame->lstCategories->getSelected(), mainGame->lstCategories->getListItem(mainGame->lstCategories->getSelected()));
DeckManager::GetCategoryPath(catepath, mainGame->lstCategories->getSelected(), mainGame->lstCategories->getListItem(mainGame->lstCategories->getSelected()));
myswprintf(filepath, L"%ls/%ls.ydk", catepath, mainGame->lstDecks->getListItem(decksel));
deckManager.LoadCurrentDeck(filepath, showing_pack);
RefreshPackListScroll();
......@@ -1653,7 +1653,7 @@ void DeckBuilder::RefreshDeckList() {
irr::gui::IGUIListBox* lstCategories = mainGame->lstCategories;
irr::gui::IGUIListBox* lstDecks = mainGame->lstDecks;
wchar_t catepath[256];
deckManager.GetCategoryPath(catepath, lstCategories->getSelected(), lstCategories->getListItem(lstCategories->getSelected()));
DeckManager::GetCategoryPath(catepath, lstCategories->getSelected(), lstCategories->getListItem(lstCategories->getSelected()));
lstDecks->clear();
mainGame->RefreshDeck(catepath, [lstDecks](const wchar_t* item) { lstDecks->addItem(item); });
}
......
......@@ -16,6 +16,7 @@ void DeckManager::LoadLFListSingle(const char* path) {
FILE* fp = myfopen(path, "r");
char linebuf[256]{};
wchar_t strBuffer[256]{};
char str1[16]{};
if(fp) {
while(std::fgets(linebuf, sizeof linebuf, fp)) {
if(linebuf[0] == '#')
......@@ -35,10 +36,11 @@ void DeckManager::LoadLFListSingle(const char* path) {
continue;
unsigned int code = 0;
int count = -1;
if (std::sscanf(linebuf, "%9u%*[ ]%9d", &code, &count) != 2)
if (std::sscanf(linebuf, "%10s%*[ ]%1d", str1, &count) != 2)
continue;
if (count < 0 || count > 2)
continue;
code = std::strtoul(str1, nullptr, 10);
cur->content[code] = count;
cur->hash = cur->hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + count)) | (code >> (5 - count)));
}
......@@ -154,13 +156,12 @@ unsigned int DeckManager::CheckDeck(const Deck& deck, unsigned int lfhash, int r
}
return 0;
}
int DeckManager::LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec, bool is_packlist) {
uint32_t DeckManager::LoadDeck(Deck& deck, uint32_t dbuf[], int mainc, int sidec, bool is_packlist) {
deck.clear();
int code;
int errorcode = 0;
uint32_t errorcode = 0;
CardData cd;
for(int i = 0; i < mainc; ++i) {
code = dbuf[i];
auto code = dbuf[i];
if(!dataManager.GetData(code, &cd)) {
errorcode = code;
continue;
......@@ -183,7 +184,7 @@ int DeckManager::LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec, bool is_p
}
}
for(int i = 0; i < sidec; ++i) {
code = dbuf[mainc + i];
auto code = dbuf[mainc + i];
if(!dataManager.GetData(code, &cd)) {
errorcode = code;
continue;
......@@ -198,22 +199,21 @@ int DeckManager::LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec, bool is_p
return errorcode;
}
#ifndef YGOPRO_SERVER_MODE
int DeckManager::LoadDeck(Deck& deck, std::istringstream& deckStream, bool is_packlist) {
size_t ct = 0;
int mainc = 0, sidec = 0, code = 0;
int cardlist[PACK_MAX_SIZE]{};
uint32_t DeckManager::LoadDeckFromStream(Deck& deck, std::istringstream& deckStream, bool is_packlist) {
int ct = 0;
int mainc = 0, sidec = 0;
uint32_t cardlist[PACK_MAX_SIZE]{};
bool is_side = false;
std::string linebuf;
while (std::getline(deckStream, linebuf, '\n') && ct < (sizeof cardlist / sizeof cardlist[0])) {
while (std::getline(deckStream, linebuf, '\n') && ct < PACK_MAX_SIZE) {
if (linebuf[0] == '!') {
is_side = true;
continue;
}
if (linebuf[0] < '0' || linebuf[0] > '9')
continue;
errno = 0;
code = std::strtol(linebuf.c_str(), nullptr, 10);
if (errno == ERANGE)
auto code = std::strtoul(linebuf.c_str(), nullptr, 10);
if (code >= UINT32_MAX)
continue;
cardlist[ct++] = code;
if (is_side)
......@@ -223,16 +223,16 @@ int DeckManager::LoadDeck(Deck& deck, std::istringstream& deckStream, bool is_pa
}
return LoadDeck(deck, cardlist, mainc, sidec, is_packlist);
}
#endif
bool DeckManager::LoadSide(Deck& deck, int* dbuf, int mainc, int sidec) {
std::unordered_map<int, int> pcount;
std::unordered_map<int, int> ncount;
#endif // YGOPRO_SERVER_MODE
bool DeckManager::LoadSide(Deck& deck, uint32_t dbuf[], int mainc, int sidec) {
std::unordered_map<uint32_t, int> pcount;
std::unordered_map<uint32_t, int> ncount;
for(size_t i = 0; i < deck.main.size(); ++i)
++pcount[deck.main[i]->first];
pcount[deck.main[i]->first]++;
for(size_t i = 0; i < deck.extra.size(); ++i)
++pcount[deck.extra[i]->first];
pcount[deck.extra[i]->first]++;
for(size_t i = 0; i < deck.side.size(); ++i)
++pcount[deck.side[i]->first];
pcount[deck.side[i]->first]++;
Deck ndeck;
LoadDeck(ndeck, dbuf, mainc, sidec);
#ifndef YGOPRO_NO_SIDE_CHECK
......@@ -240,11 +240,11 @@ bool DeckManager::LoadSide(Deck& deck, int* dbuf, int mainc, int sidec) {
return false;
#endif
for(size_t i = 0; i < ndeck.main.size(); ++i)
++ncount[ndeck.main[i]->first];
ncount[ndeck.main[i]->first]++;
for(size_t i = 0; i < ndeck.extra.size(); ++i)
++ncount[ndeck.extra[i]->first];
ncount[ndeck.extra[i]->first]++;
for(size_t i = 0; i < ndeck.side.size(); ++i)
++ncount[ndeck.side[i]->first];
ncount[ndeck.side[i]->first]++;
#ifndef YGOPRO_NO_SIDE_CHECK
for (auto& cdit : ncount)
if (cdit.second != pcount[cdit.first])
......@@ -321,8 +321,8 @@ bool DeckManager::LoadCurrentDeck(const wchar_t* file, bool is_packlist) {
return false;
}
std::istringstream deckStream(deckBuffer);
LoadDeck(current_deck, deckStream, is_packlist);
return true; // the above LoadDeck has return value but we ignore it here for now
LoadDeckFromStream(current_deck, deckStream, is_packlist);
return true; // the above function has return value but we ignore it here for now
}
bool DeckManager::LoadCurrentDeck(int category_index, const wchar_t* category_name, const wchar_t* deckname) {
wchar_t filepath[256];
......@@ -333,7 +333,7 @@ bool DeckManager::LoadCurrentDeck(int category_index, const wchar_t* category_na
mainGame->deckBuilder.RefreshPackListScroll();
return res;
}
bool DeckManager::SaveDeck(Deck& deck, const wchar_t* file) {
bool DeckManager::SaveDeck(const Deck& deck, const wchar_t* file) {
if(!FileSystem::IsDirExists(L"./deck") && !FileSystem::MakeDir(L"./deck"))
return false;
FILE* fp = OpenDeckFile(file, "w");
......@@ -341,26 +341,18 @@ bool DeckManager::SaveDeck(Deck& deck, const wchar_t* file) {
return false;
std::fprintf(fp, "#created by ...\n#main\n");
for(size_t i = 0; i < deck.main.size(); ++i)
std::fprintf(fp, "%d\n", deck.main[i]->first);
std::fprintf(fp, "%u\n", deck.main[i]->first);
std::fprintf(fp, "#extra\n");
for(size_t i = 0; i < deck.extra.size(); ++i)
std::fprintf(fp, "%d\n", deck.extra[i]->first);
std::fprintf(fp, "%u\n", deck.extra[i]->first);
std::fprintf(fp, "!side\n");
for(size_t i = 0; i < deck.side.size(); ++i)
std::fprintf(fp, "%d\n", deck.side[i]->first);
std::fprintf(fp, "%u\n", deck.side[i]->first);
std::fclose(fp);
return true;
}
bool DeckManager::DeleteDeck(const wchar_t* file) {
#ifdef _WIN32
BOOL result = DeleteFileW(file);
return !!result;
#else
char filefn[256];
BufferIO::EncodeUTF8(file, filefn);
int result = unlink(filefn);
return result == 0;
#endif
return FileSystem::RemoveFile(file);
}
int DeckManager::TypeCount(std::vector<code_pointer> list, unsigned int ctype) {
int res = 0;
......@@ -378,7 +370,7 @@ bool DeckManager::LoadDeckFromCode(Deck& deck, const unsigned char *code, int le
return false;
int mainc = BufferIO::ReadInt32(pdeck);
int sidec = BufferIO::ReadInt32(pdeck);
int errorcode = LoadDeck(deck, (int*)pdeck, mainc, sidec);
int errorcode = LoadDeck(deck, (uint32_t*)pdeck, mainc, sidec);
return (errorcode == 0);
}
int DeckManager::SaveDeckToCode(Deck& deck, unsigned char* code) {
......
......@@ -65,27 +65,30 @@ public:
const wchar_t* GetLFListName(unsigned int lfhash);
const LFList* GetLFList(unsigned int lfhash);
unsigned int CheckDeck(const Deck& deck, unsigned int lfhash, int rule);
int LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec, bool is_packlist = false);
bool LoadSide(Deck& deck, int* dbuf, int mainc, int sidec);
#ifndef YGOPRO_SERVER_MODE
int LoadDeck(Deck& deck, std::istringstream& deckStream, bool is_packlist = false);
void GetCategoryPath(wchar_t* ret, int index, const wchar_t* text);
void GetDeckFile(wchar_t* ret, int category_index, const wchar_t* category_name, const wchar_t* deckname);
FILE* OpenDeckFile(const wchar_t* file, const char* mode);
irr::io::IReadFile* OpenDeckReader(const wchar_t* file);
bool LoadCurrentDeck(const wchar_t* file, bool is_packlist = false);
bool LoadCurrentDeck(int category_index, const wchar_t* category_name, const wchar_t* deckname);
bool SaveDeck(Deck& deck, const wchar_t* file);
bool DeleteDeck(const wchar_t* file);
wchar_t DeckFormatBuffer[128];
int TypeCount(std::vector<code_pointer> list, unsigned int ctype);
bool LoadDeckFromCode(Deck& deck, const unsigned char *code, int len);
int SaveDeckToCode(Deck &deck, unsigned char *code);
bool CreateCategory(const wchar_t* name);
bool RenameCategory(const wchar_t* oldname, const wchar_t* newname);
bool DeleteCategory(const wchar_t* name);
bool SaveDeckBuffer(const int deckbuf[], const wchar_t* name);
#endif //YGOPRO_SERVER_MODE
#endif // YGOPRO_SERVER_MODE
static uint32_t LoadDeck(Deck& deck, uint32_t dbuf[], int mainc, int sidec, bool is_packlist = false);
static bool LoadSide(Deck& deck, uint32_t dbuf[], int mainc, int sidec);
#ifndef YGOPRO_SERVER_MODE
static uint32_t LoadDeckFromStream(Deck& deck, std::istringstream& deckStream, bool is_packlist = false);
static void GetCategoryPath(wchar_t* ret, int index, const wchar_t* text);
static void GetDeckFile(wchar_t* ret, int category_index, const wchar_t* category_name, const wchar_t* deckname);
static FILE* OpenDeckFile(const wchar_t* file, const char* mode);
static irr::io::IReadFile* OpenDeckReader(const wchar_t* file);
static bool SaveDeck(const Deck& deck, const wchar_t* file);
static bool DeleteDeck(const wchar_t* file);
static bool CreateCategory(const wchar_t* name);
static bool RenameCategory(const wchar_t* oldname, const wchar_t* newname);
static bool DeleteCategory(const wchar_t* name);
#endif // YGOPRO_SERVER_MODE
};
extern DeckManager deckManager;
......
......@@ -4127,7 +4127,9 @@ bool DuelClient::ClientAnalyze(unsigned char* msg, int len) {
break;
}
case MSG_RELOAD_FIELD: {
mainGame->gMutex.lock();
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) {
mainGame->gMutex.lock();
}
mainGame->dField.Clear();
mainGame->dInfo.duel_rule = BufferIO::ReadUInt8(pbuf);
int val = 0;
......@@ -4233,7 +4235,9 @@ bool DuelClient::ClientAnalyze(unsigned char* msg, int len) {
myswprintf(event_string, dataManager.GetSysString(1609), dataManager.GetName(mainGame->dField.current_chain.code));
mainGame->dField.last_chain = true;
}
mainGame->gMutex.unlock();
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) {
mainGame->gMutex.unlock();
}
break;
}
}
......
......@@ -199,6 +199,9 @@ bool Game::Initialize() {
numFont = irr::gui::CGUITTFont::createTTFont(env, gameConf.numfont, 16);
if(!numFont) {
const wchar_t* numFontPaths[] = {
L"./fonts/numFont.ttf",
L"./fonts/numFont.ttc",
L"./fonts/numFont.otf",
L"C:/Windows/Fonts/arialbd.ttf",
L"/usr/share/fonts/truetype/DroidSansFallbackFull.ttf",
L"/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc",
......@@ -206,9 +209,6 @@ bool Game::Initialize() {
L"/usr/share/fonts/noto-cjk/NotoSansCJK-Bold.ttc",
L"/System/Library/Fonts/SFNSTextCondensed-Bold.otf",
L"/System/Library/Fonts/SFNS.ttf",
L"./fonts/numFont.ttf",
L"./fonts/numFont.ttc",
L"./fonts/numFont.otf"
};
for(const wchar_t* path : numFontPaths) {
BufferIO::CopyWideString(path, gameConf.numfont);
......@@ -220,6 +220,9 @@ bool Game::Initialize() {
textFont = irr::gui::CGUITTFont::createTTFont(env, gameConf.textfont, gameConf.textfontsize);
if(!textFont) {
const wchar_t* textFontPaths[] = {
L"./fonts/textFont.ttf",
L"./fonts/textFont.ttc",
L"./fonts/textFont.otf",
L"C:/Windows/Fonts/msyh.ttc",
L"C:/Windows/Fonts/msyh.ttf",
L"C:/Windows/Fonts/simsun.ttc",
......@@ -231,9 +234,7 @@ bool Game::Initialize() {
L"/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc",
L"/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
L"/System/Library/Fonts/PingFang.ttc",
L"./fonts/textFont.ttf",
L"./fonts/textFont.ttc",
L"./fonts/textFont.otf"
L"/System/Library/Fonts/STHeiti Medium.ttc",
};
for(const wchar_t* path : textFontPaths) {
BufferIO::CopyWideString(path, gameConf.textfont);
......@@ -251,7 +252,7 @@ bool Game::Initialize() {
}
});
if(fpath[0] == 0) {
ErrorLog("Failed to load font(s)!");
ErrorLog("No fonts found! Please place appropriate font file in the fonts directory, or edit system.conf manually.");
return false;
}
if(!numFont) {
......@@ -263,6 +264,10 @@ bool Game::Initialize() {
textFont = irr::gui::CGUITTFont::createTTFont(env, gameConf.textfont, gameConf.textfontsize);
}
}
if(!numFont || !textFont) {
ErrorLog("Failed to load font(s)!");
return false;
}
adFont = irr::gui::CGUITTFont::createTTFont(env, gameConf.numfont, 12);
lpcFont = irr::gui::CGUITTFont::createTTFont(env, gameConf.numfont, 48);
guiFont = irr::gui::CGUITTFont::createTTFont(env, gameConf.textfont, gameConf.textfontsize);
......@@ -1425,7 +1430,7 @@ void Game::RefreshDeck(irr::gui::IGUIComboBox* cbCategory, irr::gui::IGUIComboBo
return;
}
wchar_t catepath[256];
deckManager.GetCategoryPath(catepath, cbCategory->getSelected(), cbCategory->getText());
DeckManager::GetCategoryPath(catepath, cbCategory->getSelected(), cbCategory->getText());
cbDeck->clear();
RefreshDeck(catepath, [cbDeck](const wchar_t* item) { cbDeck->addItem(item); });
}
......@@ -1564,14 +1569,6 @@ bool Game::LoadConfigFromFile(const char* file) {
} else if(!std::strcmp(strbuf, "errorlog")) {
unsigned int val = std::strtol(valbuf, nullptr, 10);
enable_log = val & 0xff;
} else if(!std::strcmp(strbuf, "textfont")) {
int textfontsize = 0;
if (std::sscanf(linebuf, "%63s = %959s %d", strbuf, valbuf, &textfontsize) != 3)
continue;
gameConf.textfontsize = textfontsize;
BufferIO::DecodeUTF8(valbuf, gameConf.textfont);
} else if(!std::strcmp(strbuf, "numfont")) {
BufferIO::DecodeUTF8(valbuf, gameConf.numfont);
} else if(!std::strcmp(strbuf, "serverport")) {
gameConf.serverport = std::strtol(valbuf, nullptr, 10);
} else if(!std::strcmp(strbuf, "lasthost")) {
......@@ -1674,7 +1671,18 @@ bool Game::LoadConfigFromFile(const char* file) {
// options allowing multiple words
if (std::sscanf(linebuf, "%63s = %959[^\n]", strbuf, valbuf) != 2)
continue;
if (!std::strcmp(strbuf, "nickname")) {
if (!std::strcmp(strbuf, "textfont")) {
char* last_space = std::strrchr(valbuf, ' ');
if (last_space == nullptr)
continue;
int fontsize = std::strtol(last_space + 1, nullptr, 10);
if (fontsize > 0)
gameConf.textfontsize = fontsize;
*last_space = 0;
BufferIO::DecodeUTF8(valbuf, gameConf.textfont);
} else if (!std::strcmp(strbuf, "numfont")) {
BufferIO::DecodeUTF8(valbuf, gameConf.numfont);
} else if (!std::strcmp(strbuf, "nickname")) {
BufferIO::DecodeUTF8(valbuf, gameConf.nickname);
} else if (!std::strcmp(strbuf, "gamename")) {
BufferIO::DecodeUTF8(valbuf, gameConf.gamename);
......@@ -2101,6 +2109,11 @@ void Game::AddDebugMsg(const char* msg) {
}
#ifndef YGOPRO_SERVER_MODE
void Game::ErrorLog(const char* msg) {
#ifdef _WIN32
OutputDebugStringA(msg);
#else
std::fprintf(stderr, "%s\n", msg);
#endif
FILE* fp = myfopen("error.log", "a");
if(!fp)
return;
......
......@@ -30,7 +30,7 @@ int main(int argc, char* argv[]) {
#if defined(FOPEN_WINDOWS_SUPPORT_UTF8)
std::setlocale(LC_CTYPE, ".UTF-8");
#elif defined(__APPLE__)
std::setlocale(LC_CTYPE, "C.UTF-8");
std::setlocale(LC_CTYPE, "UTF-8");
#elif !defined(_WIN32)
std::setlocale(LC_CTYPE, "");
#endif
......
#include "image_manager.h"
#include "game.h"
#include <thread>
#include "myfilesystem.h"
#ifdef YGOPRO_USE_THUMB_LOAD_THERAD
#include <thread>
#endif
#ifdef _OPENMP
#include <omp.h>
#endif
namespace ygo {
......@@ -24,8 +29,10 @@ bool ImageManager::Initial() {
tUnknownFit = nullptr;
tUnknownThumb = nullptr;
tBigPicture = nullptr;
#ifdef YGOPRO_USE_THUMB_LOAD_THERAD
tLoading = nullptr;
tThumbLoadingThreadRunning = false;
#endif
tAct = GetRandomImage(TEXTURE_ACTIVATE);
tAttack = GetRandomImage(TEXTURE_ATTACK);
if(!tAct)
......@@ -134,7 +141,11 @@ void ImageManager::ClearTexture() {
driver->removeTexture(tit->second);
}
for(auto tit = tThumb.begin(); tit != tThumb.end(); ++tit) {
#ifdef YGOPRO_USE_THUMB_LOAD_THERAD
if(tit->second && tit->second != tLoading)
#else
if(tit->second)
#endif
driver->removeTexture(tit->second);
}
if(tBigPicture != nullptr) {
......@@ -144,12 +155,14 @@ void ImageManager::ClearTexture() {
tMap[0].clear();
tMap[1].clear();
tThumb.clear();
#ifdef YGOPRO_USE_THUMB_LOAD_THERAD
tThumbLoadingMutex.lock();
tThumbLoading.clear();
while(!tThumbLoadingCodes.empty())
tThumbLoadingCodes.pop();
tThumbLoadingThreadRunning = false;
tThumbLoadingMutex.unlock();
#endif
tFields.clear();
}
void ImageManager::RemoveTexture(int code) {
......@@ -191,11 +204,13 @@ void ImageManager::ResizeTexture() {
driver->removeTexture(tUnknown);
driver->removeTexture(tUnknownFit);
driver->removeTexture(tUnknownThumb);
#ifdef YGOPRO_USE_THUMB_LOAD_THERAD
driver->removeTexture(tLoading);
tLoading = GetTextureFromFile("textures/cover.jpg", imgWidthThumb, imgHeightThumb);
#endif
tUnknown = GetTextureFromFile("textures/unknown.jpg", CARD_IMG_WIDTH, CARD_IMG_HEIGHT);
tUnknownFit = GetTextureFromFile("textures/unknown.jpg", imgWidthFit, imgHeightFit);
tUnknownThumb = GetTextureFromFile("textures/unknown.jpg", imgWidthThumb, imgHeightThumb);
tLoading = GetTextureFromFile("textures/cover.jpg", imgWidthThumb, imgHeightThumb);
driver->removeTexture(tBackGround);
tBackGround = GetRandomImage(TEXTURE_DUEL, bgWidth, bgHeight);
if(!tBackGround)
......@@ -221,25 +236,27 @@ void ImageManager::ResizeTexture() {
}
// function by Warr1024, from https://github.com/minetest/minetest/issues/2419 , modified
void imageScaleNNAA(irr::video::IImage *src, irr::video::IImage *dest) {
double sx, sy, minsx, maxsx, minsy, maxsy, area, ra, ga, ba, aa, pw, ph, pa;
irr::u32 dy, dx;
irr::video::SColor pxl;
const irr::core::dimension2d<irr::u32> srcDim = src->getDimension();
const irr::core::dimension2d<irr::u32> destDim = dest->getDimension();
// Cache rectsngle boundaries.
double sw = src->getDimension().Width * 1.0;
double sh = src->getDimension().Height * 1.0;
// Cache scale ratios.
const double rx = (double)srcDim.Width / destDim.Width;
const double ry = (double)srcDim.Height / destDim.Height;
// Walk each destination image pixel.
// Note: loop y around x for better cache locality.
irr::core::dimension2d<irr::u32> dim = dest->getDimension();
for(dy = 0; dy < dim.Height; dy++)
for(dx = 0; dx < dim.Width; dx++) {
#pragma omp parallel
{
double sx, sy, minsx, maxsx, minsy, maxsy, area, ra, ga, ba, aa, pw, ph, pa;
irr::video::SColor pxl, npxl;
// Walk each destination image pixel.
#pragma omp for schedule(dynamic)
for(irr::s32 dy = 0; dy < destDim.Height; dy++) {
for(irr::s32 dx = 0; dx < destDim.Width; dx++) {
// Calculate floating-point source rectangle bounds.
minsx = dx * sw / dim.Width;
maxsx = minsx + sw / dim.Width;
minsy = dy * sh / dim.Height;
maxsy = minsy + sh / dim.Height;
minsx = dx * rx;
maxsx = minsx + rx;
minsy = dy * ry;
maxsy = minsy + ry;
// Total area, and integral of r, g, b values over that area,
// initialized to zero, to be summed up in next loops.
......@@ -250,9 +267,8 @@ void imageScaleNNAA(irr::video::IImage *src, irr::video::IImage *dest) {
aa = 0;
// Loop over the integral pixel positions described by those bounds.
for(sy = floor(minsy); sy < maxsy; sy++)
for(sy = floor(minsy); sy < maxsy; sy++) {
for(sx = floor(minsx); sx < maxsx; sx++) {
// Calculate width, height, then area of dest pixel
// that's covered by this source pixel.
pw = 1;
......@@ -276,21 +292,20 @@ void imageScaleNNAA(irr::video::IImage *src, irr::video::IImage *dest) {
ba += pa * pxl.getBlue();
aa += pa * pxl.getAlpha();
}
}
// Set the destination image pixel to the average color.
if(area > 0) {
pxl.setRed(ra / area + 0.5);
pxl.setGreen(ga / area + 0.5);
pxl.setBlue(ba / area + 0.5);
pxl.setAlpha(aa / area + 0.5);
npxl.set((irr::u32)(aa / area + 0.5),
(irr::u32)(ra / area + 0.5),
(irr::u32)(ga / area + 0.5),
(irr::u32)(ba / area + 0.5));
} else {
pxl.setRed(0);
pxl.setGreen(0);
pxl.setBlue(0);
pxl.setAlpha(0);
npxl.set(0);
}
dest->setPixel(dx, dy, pxl);
dest->setPixel(dx, dy, npxl);
}
}
} // end of parallel region
}
irr::video::ITexture* ImageManager::GetTextureFromFile(const char* file, irr::s32 width, irr::s32 height) {
if(mainGame->gameConf.use_image_scale) {
......@@ -392,6 +407,7 @@ irr::video::ITexture* ImageManager::GetBigPicture(int code, float zoom) {
tBigPicture = texture;
return texture;
}
#ifdef YGOPRO_USE_THUMB_LOAD_THERAD
int ImageManager::LoadThumbThread() {
while(true) {
imageManager.tThumbLoadingMutex.lock();
......@@ -479,9 +495,34 @@ int ImageManager::LoadThumbThread() {
imageManager.tThumbLoadingMutex.unlock();
return 0;
}
#endif // YGOPRO_USE_THUMB_LOAD_THERAD
irr::video::ITexture* ImageManager::GetTextureThumb(int code) {
if(code == 0)
return tUnknownThumb;
#ifndef YGOPRO_USE_THUMB_LOAD_THERAD
auto tit = tThumb.find(code);
if(tit == tThumb.end()) {
char file[256];
std::snprintf(file, sizeof file, "expansions/pics/thumbnail/%d.jpg", code);
int width = CARD_THUMB_WIDTH * mainGame->xScale;
int height = CARD_THUMB_HEIGHT * mainGame->yScale;
irr::video::ITexture* img = GetTextureFromFile(file, width, height);
if(img == NULL) {
std::snprintf(file, sizeof file, "pics/thumbnail/%d.jpg", code);
img = GetTextureFromFile(file, width, height);
}
if(img == NULL && mainGame->gameConf.use_image_scale) {
std::snprintf(file, sizeof file, "expansions/pics/%d.jpg", code);
img = GetTextureFromFile(file, width, height);
if(img == NULL) {
std::snprintf(file, sizeof file, "pics/%d.jpg", code);
img = GetTextureFromFile(file, width, height);
}
}
tThumb[code] = img;
return (img == NULL) ? tUnknownThumb : img;
}
#else // YGOPRO_USE_THUMB_LOAD_THERAD
imageManager.tThumbLoadingMutex.lock();
auto lit = tThumbLoading.find(code);
if(lit != tThumbLoading.end()) {
......@@ -509,6 +550,7 @@ irr::video::ITexture* ImageManager::GetTextureThumb(int code) {
imageManager.tThumbLoadingMutex.unlock();
return tLoading;
}
#endif // YGOPRO_USE_THUMB_LOAD_THERAD
if(tit->second)
return tit->second;
else
......
#ifndef IMAGEMANAGER_H
#define IMAGEMANAGER_H
#ifndef _OPENMP
#define YGOPRO_USE_THUMB_LOAD_THERAD
#endif
#include "config.h"
#include "data_manager.h"
#include <unordered_map>
#ifdef YGOPRO_USE_THUMB_LOAD_THERAD
#include <queue>
#include <mutex>
#endif
namespace ygo {
......@@ -28,15 +34,19 @@ public:
irr::video::ITexture* GetBigPicture(int code, float zoom);
irr::video::ITexture* GetTextureThumb(int code);
irr::video::ITexture* GetTextureField(int code);
#ifdef YGOPRO_USE_THUMB_LOAD_THERAD
static int LoadThumbThread();
#endif
std::unordered_map<int, irr::video::ITexture*> tMap[2];
std::unordered_map<int, irr::video::ITexture*> tThumb;
std::unordered_map<int, irr::video::ITexture*> tFields;
#ifdef YGOPRO_USE_THUMB_LOAD_THERAD
std::unordered_map<int, irr::video::IImage*> tThumbLoading;
std::queue<int> tThumbLoadingCodes;
std::mutex tThumbLoadingMutex;
bool tThumbLoadingThreadRunning;
#endif
irr::IrrlichtDevice* device;
irr::video::IVideoDriver* driver;
irr::video::ITexture* tCover[4];
......@@ -44,7 +54,9 @@ public:
irr::video::ITexture* tUnknownFit;
irr::video::ITexture* tUnknownThumb;
irr::video::ITexture* tBigPicture;
#ifdef YGOPRO_USE_THUMB_LOAD_THERAD
irr::video::ITexture* tLoading;
#endif
irr::video::ITexture* tAct;
irr::video::ITexture* tAttack;
irr::video::ITexture* tNegated;
......
......@@ -353,7 +353,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
wchar_t arg1[512];
if(mainGame->botInfo[sel].select_deckfile) {
wchar_t botdeck[256];
deckManager.GetDeckFile(botdeck, mainGame->cbBotDeckCategory->getSelected(), mainGame->cbBotDeckCategory->getText(), mainGame->cbBotDeck->getText());
DeckManager::GetDeckFile(botdeck, mainGame->cbBotDeckCategory->getSelected(), mainGame->cbBotDeckCategory->getText(), mainGame->cbBotDeck->getText());
myswprintf(arg1, L"%ls DeckFile='%ls'", mainGame->botInfo[sel].command, botdeck);
}
else
......@@ -372,7 +372,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
wchar_t warg1[512];
if(mainGame->botInfo[sel].select_deckfile) {
wchar_t botdeck[256];
deckManager.GetDeckFile(botdeck, mainGame->cbBotDeckCategory->getSelected(), mainGame->cbBotDeckCategory->getText(), mainGame->cbBotDeck->getText());
DeckManager::GetDeckFile(botdeck, mainGame->cbBotDeckCategory->getSelected(), mainGame->cbBotDeckCategory->getText(), mainGame->cbBotDeck->getText());
myswprintf(warg1, L"%ls DeckFile='%ls'", mainGame->botInfo[sel].command, botdeck);
}
else
......
......@@ -86,6 +86,14 @@ public:
return DeleteDir(wdir);
}
static bool RemoveFile(const wchar_t* wfile) {
return DeleteFileW(wfile);
}
static bool RemoveFile(const char* file) {
return DeleteFileA(file);
}
static void TraversalDir(const wchar_t* wpath, const std::function<void(const wchar_t*, bool)>& cb) {
wchar_t findstr[1024];
std::swprintf(findstr, sizeof findstr / sizeof findstr[0], L"%ls/*", wpath);
......@@ -195,6 +203,16 @@ public:
return success;
}
static bool RemoveFile(const wchar_t* wfile) {
char file[1024];
BufferIO::EncodeUTF8(wfile, file);
return RemoveFile(file);
}
static bool RemoveFile(const char* file) {
return unlink(file) == 0;
}
#ifndef YGOPRO_SERVER_MODE
struct file_unit {
std::string filename;
......
......@@ -27,7 +27,7 @@ struct HostInfo {
uint8_t no_shuffle_deck{};
// byte padding[3]
uint32_t start_lp{};
int32_t start_lp{};
uint8_t start_hand{};
uint8_t draw_count{};
uint16_t time_limit{};
......@@ -57,7 +57,7 @@ static_assert(sizeof(HostRequest) == 2, "size mismatch: HostRequest");
struct CTOS_DeckData {
int32_t mainc{};
int32_t sidec{};
int32_t list[MAINC_MAX + SIDEC_MAX]{};
uint32_t list[MAINC_MAX + SIDEC_MAX]{};
};
check_trivially_copyable(CTOS_DeckData);
......
......@@ -47,6 +47,7 @@ project "ygopro"
kind "WindowedApp"
cppdialect "C++14"
rtti "Off"
openmp "On"
files { "*.cpp", "*.h" }
includedirs { "../ocgcore" }
......@@ -111,9 +112,6 @@ end
filter "system:windows"
defines { "_IRR_WCHAR_FILESYSTEM" }
files "ygopro.rc"
if not SERVER_MODE then
libdirs { "$(DXSDK_DIR)Lib/x86" }
end
if SERVER_PRO2_SUPPORT then
targetname ("AI.Server")
end
......@@ -137,6 +135,7 @@ end
links { "event_pthreads", "dl", "pthread", "resolv" }
filter "system:macosx"
if not SERVER_MODE then
openmp "Off"
links { "z" }
defines { "GL_SILENCE_DEPRECATION" }
end
......@@ -151,6 +150,7 @@ end
linkoptions { "-static-libstdc++", "-static-libgcc" }
if not SERVER_MODE then
links { "GL", "X11", "Xxf86vm" }
linkoptions { "-fopenmp" }
end
if USE_AUDIO and AUDIO_LIB == "irrklang" then
links { "IrrKlang" }
......
......@@ -199,15 +199,7 @@ bool Replay::CheckReplay(const wchar_t* name) {
bool Replay::DeleteReplay(const wchar_t* name) {
wchar_t fname[256];
myswprintf(fname, L"./replay/%ls", name);
#ifdef _WIN32
BOOL result = DeleteFileW(fname);
return !!result;
#else
char filefn[256];
BufferIO::EncodeUTF8(fname, filefn);
int result = unlink(filefn);
return result == 0;
#endif
return FileSystem::RemoveFile(fname);
}
bool Replay::RenameReplay(const wchar_t* oldname, const wchar_t* newname) {
wchar_t oldfname[256];
......
......@@ -26,13 +26,13 @@ constexpr int MAX_COMP_SIZE = UINT16_MAX + 1;
#endif // YGOPRO_SERVER_MODE
struct ReplayHeader {
unsigned int id{};
unsigned int version{};
unsigned int flag{};
unsigned int seed{};
unsigned int datasize{};
unsigned int start_time{};
unsigned char props[8]{};
uint32_t id{};
uint32_t version{};
uint32_t flag{};
uint32_t seed{};
uint32_t datasize{};
uint32_t start_time{};
uint8_t props[8]{};
};
class Replay {
......
......@@ -419,9 +419,9 @@ void SingleDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) {
return;
}
if(duel_count == 0) {
deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], deckbuf.list, deckbuf.mainc, deckbuf.sidec);
deck_error[dp->type] = DeckManager::LoadDeck(pdeck[dp->type], deckbuf.list, deckbuf.mainc, deckbuf.sidec);
} else {
if(deckManager.LoadSide(pdeck[dp->type], deckbuf.list, deckbuf.mainc, deckbuf.sidec)) {
if(DeckManager::LoadSide(pdeck[dp->type], deckbuf.list, deckbuf.mainc, deckbuf.sidec)) {
ready[dp->type] = true;
NetServer::SendPacketToPlayer(dp, STOC_DUEL_START);
if(ready[0] && ready[1]) {
......
......@@ -404,7 +404,7 @@ void TagDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) {
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
return;
}
deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], deckbuf.list, deckbuf.mainc, deckbuf.sidec);
deck_error[dp->type] = DeckManager::LoadDeck(pdeck[dp->type], deckbuf.list, deckbuf.mainc, deckbuf.sidec);
}
void TagDuel::StartDuel(DuelPlayer* dp) {
if(dp != host_player)
......
This diff is collapsed.
Subproject commit 8c8f4a9ca3f2844fe537ec7577af6d2e4dfcc711
Subproject commit ea1f4623b88d12998e548bf7fc06cc163ec823dc
......@@ -11,3 +11,4 @@ project "event"
filter "system:windows"
prebuildcommands { "xcopy /E /Y $(ProjectDir)..\\event\\WIN32-Code $(ProjectDir)..\\event\\include" }
files { "win32select.c", "evthread_win32.c", "buffer_iocp.c", "event_iocp.c", "bufferevent_async.c" }
defines { "WIN32" } -- quirk of old libevent
defines {
"_IRR_STATIC_LIB_",
"NO_IRR_USE_NON_SYSTEM_BZLIB_",
"NO_IRR_COMPILE_WITH_BZIP2_",
"NO_IRR_COMPILE_WITH_CONSOLE_DEVICE_",
"NO_IRR_COMPILE_WITH_DIRECT3D_8_",
"NO_IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_",
"NO_IRR_COMPILE_WITH_JOYSTICK_EVENTS_",
"NO_IRR_COMPILE_WITH_SOFTWARE_",
"NO_IRR_COMPILE_WITH_BURNINGSVIDEO_",
"NO_IRR_COMPILE_WITH_IRR_SCENE_LOADER_",
"NO_IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_",
"NO_IRR_COMPILE_WITH_IRR_MESH_LOADER_",
"NO_IRR_COMPILE_WITH_HALFLIFE_LOADER_",
"NO_IRR_COMPILE_WITH_MD2_LOADER_",
"NO_IRR_COMPILE_WITH_MD3_LOADER_",
"NO_IRR_COMPILE_WITH_3DS_LOADER_",
"NO_IRR_COMPILE_WITH_COLLADA_LOADER_",
"NO_IRR_COMPILE_WITH_CSM_LOADER_",
"NO_IRR_COMPILE_WITH_BSP_LOADER_",
"NO_IRR_COMPILE_WITH_DMF_LOADER_",
"NO_IRR_COMPILE_WITH_LMTS_LOADER_",
"NO_IRR_COMPILE_WITH_MY3D_LOADER_",
"NO_IRR_COMPILE_WITH_OBJ_LOADER_",
"NO_IRR_COMPILE_WITH_OCT_LOADER_",
"NO_IRR_COMPILE_WITH_LWO_LOADER_",
"NO_IRR_COMPILE_WITH_STL_LOADER_",
"NO_IRR_COMPILE_WITH_PLY_LOADER_",
"NO_IRR_COMPILE_WITH_SMF_LOADER_",
"NO_IRR_COMPILE_WITH_IRR_WRITER_",
"NO_IRR_COMPILE_WITH_COLLADA_WRITER_",
"NO_IRR_COMPILE_WITH_STL_WRITER_",
"NO_IRR_COMPILE_WITH_OBJ_WRITER_",
"NO_IRR_COMPILE_WITH_PLY_WRITER_",
"NO_IRR_COMPILE_WITH_PCX_LOADER_",
"NO_IRR_COMPILE_WITH_PPM_LOADER_",
"NO_IRR_COMPILE_WITH_PSD_LOADER_",
"NO_IRR_COMPILE_WITH_TGA_LOADER_",
"NO_IRR_COMPILE_WITH_WAL_LOADER_",
"NO_IRR_COMPILE_WITH_LMP_LOADER_",
"NO_IRR_COMPILE_WITH_RGB_LOADER_",
"NO_IRR_COMPILE_WITH_PCX_WRITER_",
"NO_IRR_COMPILE_WITH_PPM_WRITER_",
"NO_IRR_COMPILE_WITH_PSD_WRITER_",
"NO_IRR_COMPILE_WITH_TGA_WRITER_",
"NO__IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_",
"NO__IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_",
"NO__IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_",
}
This diff is collapsed.
......@@ -6,7 +6,7 @@ LUA_LIB_NAME = "lua"
BUILD_EVENT = os.istarget("windows")
BUILD_FREETYPE = os.istarget("windows")
BUILD_SQLITE = os.istarget("windows")
BUILD_IRRLICHT = not os.istarget("macosx")
BUILD_IRRLICHT = true
USE_AUDIO = true
AUDIO_LIB = "miniaudio"
......@@ -396,7 +396,6 @@ workspace "YGOPro"
end
filter "system:windows"
defines { "WIN32", "_WIN32" }
if not SERVER_PRO3_SUPPORT then
entrypoint "mainCRTStartup"
end
......@@ -414,7 +413,6 @@ end
filter "system:macosx"
libdirs { "/usr/local/lib" }
buildoptions { "-stdlib=libc++" }
if MAC_ARM then
buildoptions { "--target=arm64-apple-macos12" }
end
......
Subproject commit 1c8a21cd877e82b9bbdd95fe71f0a1b58b909797
Subproject commit 4b650142a9910444f420cd2c5e1039f7b39681ab
......@@ -1259,3 +1259,6 @@
!setname 0x1c6 统王 ドミナス
!setname 0x1c7 塞勒凯特 Serket
!setname 0x1c8 阿匹卜 Apophis
!setname 0x1c9 星辰 ドラゴンテイル
!setname 0x1ca 味美喵 ヤミー
!setname 0x1cb K9
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