Commit e0abe3c8 authored by nanahira's avatar nanahira

Merge branch 'master' of github.com:Fluorohydride/ygopro into next-mt

parents ab98f48b ec24699d
...@@ -65,7 +65,7 @@ jobs: ...@@ -65,7 +65,7 @@ jobs:
id: premake id: premake
uses: mercury233/action-cache-download-file@v1.0.0 uses: mercury233/action-cache-download-file@v1.0.0
with: with:
url: https://github.com/premake/premake-core/releases/download/v5.0.0-beta6/premake-5.0.0-beta6-windows.zip url: https://github.com/premake/premake-core/releases/download/v5.0.0-beta7/premake-5.0.0-beta7-windows.zip
filename: premake5.zip filename: premake5.zip
- name: Extract premake - name: Extract premake
...@@ -99,12 +99,12 @@ jobs: ...@@ -99,12 +99,12 @@ jobs:
id: lua id: lua
uses: mercury233/action-cache-download-file@v1.0.0 uses: mercury233/action-cache-download-file@v1.0.0
with: with:
url: https://www.lua.org/ftp/lua-5.4.7.tar.gz url: https://www.lua.org/ftp/lua-5.4.8.tar.gz
- name: Extract lua - name: Extract lua
run: | run: |
tar xf ${{ steps.lua.outputs.filepath }} tar xf ${{ steps.lua.outputs.filepath }}
move lua-5.4.7 lua move lua-5.4.8 lua
- name: Download sqlite - name: Download sqlite
id: sqlite id: sqlite
...@@ -258,7 +258,7 @@ jobs: ...@@ -258,7 +258,7 @@ jobs:
premake-version: 5.0.0-beta4 premake-version: 5.0.0-beta4
- name: ubuntu-24 - name: ubuntu-24
os: ubuntu-24.04 os: ubuntu-24.04
premake-version: 5.0.0-beta6 premake-version: 5.0.0-beta7
- name: ubuntu-static-link - name: ubuntu-static-link
os: ubuntu-22.04 os: ubuntu-22.04
premake-version: 5.0.0-beta4 premake-version: 5.0.0-beta4
...@@ -345,12 +345,12 @@ jobs: ...@@ -345,12 +345,12 @@ jobs:
id: lua id: lua
uses: mercury233/action-cache-download-file@v1.0.0 uses: mercury233/action-cache-download-file@v1.0.0
with: with:
url: https://www.lua.org/ftp/lua-5.4.7.tar.gz url: https://www.lua.org/ftp/lua-5.4.8.tar.gz
- name: Extract lua - name: Extract lua
run: | run: |
tar xf ${{ steps.lua.outputs.filepath }} tar xf ${{ steps.lua.outputs.filepath }}
mv lua-5.4.7 lua mv lua-5.4.8 lua
- name: Download sqlite - name: Download sqlite
if: matrix.static-link == true if: matrix.static-link == true
...@@ -528,9 +528,17 @@ jobs: ...@@ -528,9 +528,17 @@ jobs:
brew install opus opusfile libvorbis brew install opus opusfile libvorbis
# brew install sqlite libx11 freetype libevent # brew install sqlite libx11 freetype libevent
- name: Install premake - name: Download premake
id: premake
uses: mercury233/action-cache-download-file@v1.0.0
with:
url: https://github.com/premake/premake-core/releases/download/v5.0.0-beta7/premake-5.0.0-beta7-macosx.tar.gz
filename: premake5.tar.gz
- name: Extract premake
run: | run: |
brew install premake tar xf ${{ steps.premake.outputs.filepath }}
chmod +x ./premake5
- name: Download libevent - name: Download libevent
if: matrix.static-link == true if: matrix.static-link == true
...@@ -571,12 +579,12 @@ jobs: ...@@ -571,12 +579,12 @@ jobs:
id: lua id: lua
uses: mercury233/action-cache-download-file@v1.0.0 uses: mercury233/action-cache-download-file@v1.0.0
with: with:
url: https://www.lua.org/ftp/lua-5.4.7.tar.gz url: https://www.lua.org/ftp/lua-5.4.8.tar.gz
- name: Extract lua - name: Extract lua
run: | run: |
tar xf ${{ steps.lua.outputs.filepath }} tar xf ${{ steps.lua.outputs.filepath }}
mv lua-5.4.7 lua mv lua-5.4.8 lua
- name: Download sqlite - name: Download sqlite
if: matrix.static-link == true if: matrix.static-link == true
...@@ -662,12 +670,12 @@ jobs: ...@@ -662,12 +670,12 @@ jobs:
- name: Use premake to generate make files (Homebrew packages) - name: Use premake to generate make files (Homebrew packages)
if: matrix.static-link != true if: matrix.static-link != true
run: | run: |
DYLD_LIBRARY_PATH=$(brew --prefix)/lib premake5 gmake DYLD_LIBRARY_PATH=$(brew --prefix)/lib ./premake5 gmake
- name: Use premake to generate make files (static link) - name: Use premake to generate make files (static link)
if: matrix.static-link == true if: matrix.static-link == true
run: | run: |
premake5 gmake ${{ matrix.cross-build-intel == true && '--mac-intel' || '' }} ${{ matrix.cross-build-arm == true && '--mac-arm' || '' }} \ ./premake5 gmake ${{ matrix.cross-build-intel == true && '--mac-intel' || '' }} ${{ matrix.cross-build-arm == true && '--mac-arm' || '' }} \
--build-event \ --build-event \
--build-freetype \ --build-freetype \
--build-sqlite \ --build-sqlite \
...@@ -684,4 +692,4 @@ jobs: ...@@ -684,4 +692,4 @@ jobs:
with: with:
name: YGOPro-${{ matrix.name }} name: YGOPro-${{ matrix.name }}
path: | path: |
bin/release/YGOPro.app bin/release/YGOPro
...@@ -394,6 +394,29 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -394,6 +394,29 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
prev_operation = id; prev_operation = id;
break; break;
} }
case BUTTON_IMPORT_DECK_CODE: {
time_t nowtime = std::time(nullptr);
wchar_t timetext[40];
std::wcsftime(timetext, sizeof timetext / sizeof timetext[0], L"%Y-%m-%d %H-%M-%S", std::localtime(&nowtime));
mainGame->gMutex.lock();
mainGame->stDMMessage->setText(dataManager.GetSysString(1471));
mainGame->ebDMName->setVisible(true);
mainGame->ebDMName->setText(timetext);
mainGame->PopupElement(mainGame->wDMQuery);
mainGame->gMutex.unlock();
prev_operation = id;
break;
}
case BUTTON_EXPORT_DECK_CODE: {
std::stringstream textStream;
deckManager.SaveDeck(deckManager.current_deck, textStream);
wchar_t text[0x10000];
BufferIO::DecodeUTF8(textStream.str().c_str(), text);
mainGame->env->getOSOperator()->copyToClipboard(text);
mainGame->stACMessage->setText(dataManager.GetSysString(1480));
mainGame->PopupElement(mainGame->wACMessage, 20);
break;
}
case BUTTON_DM_OK: { case BUTTON_DM_OK: {
switch(prev_operation) { switch(prev_operation) {
case BUTTON_NEW_CATEGORY: { case BUTTON_NEW_CATEGORY: {
...@@ -470,7 +493,8 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -470,7 +493,8 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
} }
break; break;
} }
case BUTTON_NEW_DECK: { case BUTTON_NEW_DECK:
case BUTTON_IMPORT_DECK_CODE: {
const wchar_t* deckname = mainGame->ebDMName->getText(); const wchar_t* deckname = mainGame->ebDMName->getText();
wchar_t catepath[256]; wchar_t catepath[256];
DeckManager::GetCategoryPath(catepath, mainGame->cbDBCategory->getSelected(), mainGame->cbDBCategory->getText()); DeckManager::GetCategoryPath(catepath, mainGame->cbDBCategory->getSelected(), mainGame->cbDBCategory->getText());
...@@ -478,9 +502,19 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -478,9 +502,19 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
myswprintf(filepath, L"%ls/%ls.ydk", catepath, deckname); myswprintf(filepath, L"%ls/%ls.ydk", catepath, deckname);
bool res = false; bool res = false;
if(!FileSystem::IsFileExists(filepath)) { if(!FileSystem::IsFileExists(filepath)) {
deckManager.current_deck.main.clear(); if(prev_operation == BUTTON_NEW_DECK) {
deckManager.current_deck.extra.clear(); deckManager.current_deck.main.clear();
deckManager.current_deck.side.clear(); deckManager.current_deck.extra.clear();
deckManager.current_deck.side.clear();
} else {
const wchar_t* txt = mainGame->env->getOSOperator()->getTextFromClipboard();
if(txt) {
char text[0x10000];
BufferIO::EncodeUTF8(txt, text);
std::istringstream textStream(text);
deckManager.LoadCurrentDeck(textStream);
}
}
res = DeckManager::SaveDeck(deckManager.current_deck, filepath); res = DeckManager::SaveDeck(deckManager.current_deck, filepath);
RefreshDeckList(); RefreshDeckList();
ChangeCategory(mainGame->lstCategories->getSelected()); ChangeCategory(mainGame->lstCategories->getSelected());
......
...@@ -287,6 +287,10 @@ irr::io::IReadFile* DeckManager::OpenDeckReader(const wchar_t* file) { ...@@ -287,6 +287,10 @@ irr::io::IReadFile* DeckManager::OpenDeckReader(const wchar_t* file) {
#endif #endif
return reader; return reader;
} }
bool DeckManager::LoadCurrentDeck(std::istringstream& deckStream, bool is_packlist) {
LoadDeckFromStream(current_deck, deckStream, is_packlist);
return true; // the above LoadDeck has return value but we ignore it here for now
}
bool DeckManager::LoadCurrentDeck(const wchar_t* file, bool is_packlist) { bool DeckManager::LoadCurrentDeck(const wchar_t* file, bool is_packlist) {
current_deck.clear(); current_deck.clear();
auto reader = OpenDeckReader(file); auto reader = OpenDeckReader(file);
...@@ -321,21 +325,27 @@ bool DeckManager::LoadCurrentDeck(int category_index, const wchar_t* category_na ...@@ -321,21 +325,27 @@ bool DeckManager::LoadCurrentDeck(int category_index, const wchar_t* category_na
mainGame->deckBuilder.RefreshPackListScroll(); mainGame->deckBuilder.RefreshPackListScroll();
return res; return res;
} }
void DeckManager::SaveDeck(const Deck& deck, std::stringstream& deckStream) {
deckStream << "#created by ..." << std::endl;
deckStream << "#main" << std::endl;
for(size_t i = 0; i < deck.main.size(); ++i)
deckStream << deck.main[i]->first << std::endl;
deckStream << "#extra" << std::endl;
for(size_t i = 0; i < deck.extra.size(); ++i)
deckStream << deck.extra[i]->first << std::endl;
deckStream << "!side" << std::endl;
for(size_t i = 0; i < deck.side.size(); ++i)
deckStream << deck.side[i]->first << std::endl;
}
bool DeckManager::SaveDeck(const 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")) if(!FileSystem::IsDirExists(L"./deck") && !FileSystem::MakeDir(L"./deck"))
return false; return false;
FILE* fp = OpenDeckFile(file, "w"); FILE* fp = OpenDeckFile(file, "w");
if(!fp) if(!fp)
return false; return false;
std::fprintf(fp, "#created by ...\n#main\n"); std::stringstream deckStream;
for(size_t i = 0; i < deck.main.size(); ++i) SaveDeck(deck, deckStream);
std::fprintf(fp, "%u\n", deck.main[i]->first); std::fwrite(deckStream.str().c_str(), 1, deckStream.str().length(), fp);
std::fprintf(fp, "#extra\n");
for(size_t i = 0; i < deck.extra.size(); ++i)
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, "%u\n", deck.side[i]->first);
std::fclose(fp); std::fclose(fp);
return true; return true;
} }
......
...@@ -74,6 +74,7 @@ public: ...@@ -74,6 +74,7 @@ public:
#ifndef YGOPRO_SERVER_MODE #ifndef YGOPRO_SERVER_MODE
bool LoadCurrentDeck(const wchar_t* file, bool is_packlist = false); 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 LoadCurrentDeck(int category_index, const wchar_t* category_name, const wchar_t* deckname);
bool LoadCurrentDeck(std::istringstream& deckStream, bool is_packlist = false);
#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 uint32_t LoadDeck(Deck& deck, uint32_t dbuf[], int mainc, int sidec, bool is_packlist = false);
...@@ -85,6 +86,7 @@ public: ...@@ -85,6 +86,7 @@ public:
static FILE* OpenDeckFile(const wchar_t* file, const char* mode); static FILE* OpenDeckFile(const wchar_t* file, const char* mode);
static irr::io::IReadFile* OpenDeckReader(const wchar_t* file); static irr::io::IReadFile* OpenDeckReader(const wchar_t* file);
static bool SaveDeck(const Deck& deck, const wchar_t* file); static bool SaveDeck(const Deck& deck, const wchar_t* file);
static void SaveDeck(const Deck& deck, std::stringstream& deckStream);
static bool DeleteDeck(const wchar_t* file); static bool DeleteDeck(const wchar_t* file);
static bool CreateCategory(const wchar_t* name); static bool CreateCategory(const wchar_t* name);
static bool RenameCategory(const wchar_t* oldname, const wchar_t* newname); static bool RenameCategory(const wchar_t* oldname, const wchar_t* newname);
......
...@@ -715,7 +715,7 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) { ...@@ -715,7 +715,7 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) {
break; break;
} }
case STOC_REPLAY: { case STOC_REPLAY: {
if (len < 1 + (int)sizeof(ReplayHeader)) if (len < 1 + (int)sizeof(ExtendedReplayHeader))
return; return;
mainGame->gMutex.lock(); mainGame->gMutex.lock();
mainGame->wPhase->setVisible(false); mainGame->wPhase->setVisible(false);
...@@ -726,10 +726,10 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) { ...@@ -726,10 +726,10 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) {
Replay new_replay; Replay new_replay;
std::memcpy(&new_replay.pheader, prep, sizeof(new_replay.pheader)); std::memcpy(&new_replay.pheader, prep, sizeof(new_replay.pheader));
time_t starttime; time_t starttime;
if (new_replay.pheader.flag & REPLAY_UNIFORM) if (new_replay.pheader.base.flag & REPLAY_UNIFORM)
starttime = new_replay.pheader.start_time; starttime = new_replay.pheader.base.start_time;
else else
starttime = new_replay.pheader.seed; starttime = new_replay.pheader.base.seed;
wchar_t timetext[40]; wchar_t timetext[40];
std::wcsftime(timetext, sizeof timetext / sizeof timetext[0], L"%Y-%m-%d %H-%M-%S", std::localtime(&starttime)); std::wcsftime(timetext, sizeof timetext / sizeof timetext[0], L"%Y-%m-%d %H-%M-%S", std::localtime(&starttime));
...@@ -751,9 +751,9 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) { ...@@ -751,9 +751,9 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) {
mainGame->WaitFrameSignal(30); mainGame->WaitFrameSignal(30);
} }
if(mainGame->actionParam || !is_host) { if(mainGame->actionParam || !is_host) {
prep += sizeof(ReplayHeader); prep += sizeof new_replay.pheader;
std::memcpy(new_replay.comp_data, prep, len - sizeof(ReplayHeader) - 1); std::memcpy(new_replay.comp_data, prep, len - sizeof new_replay.pheader - 1);
new_replay.comp_size = len - sizeof(ReplayHeader) - 1; new_replay.comp_size = len - sizeof new_replay.pheader - 1;
if(mainGame->actionParam) if(mainGame->actionParam)
new_replay.SaveReplay(mainGame->ebRSName->getText()); new_replay.SaveReplay(mainGame->ebRSName->getText());
else else
......
...@@ -679,10 +679,10 @@ bool Game::Initialize() { ...@@ -679,10 +679,10 @@ bool Game::Initialize() {
wDeckEdit->setVisible(false); wDeckEdit->setVisible(false);
btnManageDeck = env->addButton(irr::core::rect<irr::s32>(225, 5, 290, 30), wDeckEdit, BUTTON_MANAGE_DECK, dataManager.GetSysString(1328)); btnManageDeck = env->addButton(irr::core::rect<irr::s32>(225, 5, 290, 30), wDeckEdit, BUTTON_MANAGE_DECK, dataManager.GetSysString(1328));
//deck manage //deck manage
wDeckManage = env->addWindow(irr::core::rect<irr::s32>(310, 135, 800, 465), false, dataManager.GetSysString(1460), 0, WINDOW_DECK_MANAGE); wDeckManage = env->addWindow(irr::core::rect<irr::s32>(310, 135, 800, 515), false, dataManager.GetSysString(1460), 0, WINDOW_DECK_MANAGE);
wDeckManage->setVisible(false); wDeckManage->setVisible(false);
lstCategories = env->addListBox(irr::core::rect<irr::s32>(10, 30, 140, 320), wDeckManage, LISTBOX_CATEGORIES, true); lstCategories = env->addListBox(irr::core::rect<irr::s32>(10, 30, 140, 370), wDeckManage, LISTBOX_CATEGORIES, true);
lstDecks = env->addListBox(irr::core::rect<irr::s32>(150, 30, 340, 320), wDeckManage, LISTBOX_DECKS, true); lstDecks = env->addListBox(irr::core::rect<irr::s32>(150, 30, 340, 370), wDeckManage, LISTBOX_DECKS, true);
posY = 30; posY = 30;
btnNewCategory = env->addButton(irr::core::rect<irr::s32>(350, posY, 480, posY + 25), wDeckManage, BUTTON_NEW_CATEGORY, dataManager.GetSysString(1461)); btnNewCategory = env->addButton(irr::core::rect<irr::s32>(350, posY, 480, posY + 25), wDeckManage, BUTTON_NEW_CATEGORY, dataManager.GetSysString(1461));
posY += 35; posY += 35;
...@@ -699,6 +699,10 @@ bool Game::Initialize() { ...@@ -699,6 +699,10 @@ bool Game::Initialize() {
btnMoveDeck = env->addButton(irr::core::rect<irr::s32>(350, posY, 480, posY + 25), wDeckManage, BUTTON_MOVE_DECK, dataManager.GetSysString(1467)); btnMoveDeck = env->addButton(irr::core::rect<irr::s32>(350, posY, 480, posY + 25), wDeckManage, BUTTON_MOVE_DECK, dataManager.GetSysString(1467));
posY += 35; posY += 35;
btnCopyDeck = env->addButton(irr::core::rect<irr::s32>(350, posY, 480, posY + 25), wDeckManage, BUTTON_COPY_DECK, dataManager.GetSysString(1468)); btnCopyDeck = env->addButton(irr::core::rect<irr::s32>(350, posY, 480, posY + 25), wDeckManage, BUTTON_COPY_DECK, dataManager.GetSysString(1468));
posY += 35;
btnImportDeckCode = env->addButton(irr::core::rect<irr::s32>(350, posY, 480, posY + 25), wDeckManage, BUTTON_IMPORT_DECK_CODE, dataManager.GetSysString(1478));
posY += 35;
btnExportDeckCode = env->addButton(irr::core::rect<irr::s32>(350, posY, 480, posY + 25), wDeckManage, BUTTON_EXPORT_DECK_CODE, dataManager.GetSysString(1479));
//deck manage query //deck manage query
wDMQuery = env->addWindow(irr::core::rect<irr::s32>(400, 200, 710, 320), false, dataManager.GetSysString(1460)); wDMQuery = env->addWindow(irr::core::rect<irr::s32>(400, 200, 710, 320), false, dataManager.GetSysString(1460));
wDMQuery->getCloseButton()->setVisible(false); wDMQuery->getCloseButton()->setVisible(false);
...@@ -1940,7 +1944,7 @@ void Game::OnResize() { ...@@ -1940,7 +1944,7 @@ void Game::OnResize() {
ebDeckname->setRelativePosition(Resize(80, 65, 220, 90)); ebDeckname->setRelativePosition(Resize(80, 65, 220, 90));
cbDBCategory->setRelativePosition(Resize(80, 5, 220, 30)); cbDBCategory->setRelativePosition(Resize(80, 5, 220, 30));
btnManageDeck->setRelativePosition(Resize(225, 5, 290, 30)); btnManageDeck->setRelativePosition(Resize(225, 5, 290, 30));
wDeckManage->setRelativePosition(ResizeWin(310, 135, 800, 465)); wDeckManage->setRelativePosition(ResizeWin(310, 135, 800, 515));
scrPackCards->setRelativePosition(Resize(775, 161, 795, 629)); scrPackCards->setRelativePosition(Resize(775, 161, 795, 629));
wSort->setRelativePosition(Resize(930, 132, 1020, 156)); wSort->setRelativePosition(Resize(930, 132, 1020, 156));
......
...@@ -582,6 +582,8 @@ public: ...@@ -582,6 +582,8 @@ public:
irr::gui::IGUIButton* btnDMDeleteDeck; irr::gui::IGUIButton* btnDMDeleteDeck;
irr::gui::IGUIButton* btnMoveDeck; irr::gui::IGUIButton* btnMoveDeck;
irr::gui::IGUIButton* btnCopyDeck; irr::gui::IGUIButton* btnCopyDeck;
irr::gui::IGUIButton* btnImportDeckCode;
irr::gui::IGUIButton* btnExportDeckCode;
irr::gui::IGUIWindow* wDMQuery; irr::gui::IGUIWindow* wDMQuery;
irr::gui::IGUIStaticText* stDMMessage; irr::gui::IGUIStaticText* stDMMessage;
irr::gui::IGUIStaticText* stDMMessage2; irr::gui::IGUIStaticText* stDMMessage2;
...@@ -846,6 +848,8 @@ extern unsigned int pre_seed[3]; ...@@ -846,6 +848,8 @@ extern unsigned int pre_seed[3];
#define LISTBOX_DECKS 340 #define LISTBOX_DECKS 340
#define BUTTON_DM_OK 341 #define BUTTON_DM_OK 341
#define BUTTON_DM_CANCEL 342 #define BUTTON_DM_CANCEL 342
#define BUTTON_IMPORT_DECK_CODE 343
#define BUTTON_EXPORT_DECK_CODE 344
#define COMBOBOX_LFLIST 349 #define COMBOBOX_LFLIST 349
#define BUTTON_CLEAR_LOG 350 #define BUTTON_CLEAR_LOG 350
......
...@@ -309,7 +309,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -309,7 +309,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
myswprintf(replay_path, L"./replay/%ls", replay_filename); myswprintf(replay_path, L"./replay/%ls", replay_filename);
if (!replay.OpenReplay(replay_path)) if (!replay.OpenReplay(replay_path))
break; break;
if (replay.pheader.flag & REPLAY_SINGLE_MODE) if (replay.pheader.base.flag & REPLAY_SINGLE_MODE)
break; break;
for (size_t i = 0; i < replay.decks.size(); ++i) { for (size_t i = 0; i < replay.decks.size(); ++i) {
BufferIO::CopyWideString(replay.players[Replay::GetDeckPlayer(i)].c_str(), namebuf[i]); BufferIO::CopyWideString(replay.players[Replay::GetDeckPlayer(i)].c_str(), namebuf[i]);
...@@ -537,24 +537,25 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -537,24 +537,25 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
wchar_t infobuf[256]{}; wchar_t infobuf[256]{};
std::wstring repinfo; std::wstring repinfo;
time_t curtime; time_t curtime;
if(temp_replay.pheader.flag & REPLAY_UNIFORM) const auto& rh = temp_replay.pheader.base;
curtime = temp_replay.pheader.start_time; if(temp_replay.pheader.base.flag & REPLAY_UNIFORM)
curtime = rh.start_time;
else{ else{
curtime = temp_replay.pheader.seed; curtime = rh.seed;
wchar_t version_info[256]{}; wchar_t version_info[256]{};
myswprintf(version_info, L"version 0x%X\n", temp_replay.pheader.version); myswprintf(version_info, L"version 0x%X\n", rh.version);
repinfo.append(version_info); repinfo.append(version_info);
} }
std::wcsftime(infobuf, sizeof infobuf / sizeof infobuf[0], L"%Y/%m/%d %H:%M:%S\n", std::localtime(&curtime)); std::wcsftime(infobuf, sizeof infobuf / sizeof infobuf[0], L"%Y/%m/%d %H:%M:%S\n", std::localtime(&curtime));
repinfo.append(infobuf); repinfo.append(infobuf);
if (temp_replay.pheader.flag & REPLAY_SINGLE_MODE) { if (rh.flag & REPLAY_SINGLE_MODE) {
wchar_t path[256]{}; wchar_t path[256]{};
BufferIO::DecodeUTF8(temp_replay.script_name.c_str(), path); BufferIO::DecodeUTF8(temp_replay.script_name.c_str(), path);
repinfo.append(path); repinfo.append(path);
repinfo.append(L"\n"); repinfo.append(L"\n");
} }
const auto& player_names = temp_replay.players; const auto& player_names = temp_replay.players;
if(temp_replay.pheader.flag & REPLAY_TAG) if(rh.flag & REPLAY_TAG)
myswprintf(infobuf, L"%ls\n%ls\n===VS===\n%ls\n%ls\n", player_names[0].c_str(), player_names[1].c_str(), player_names[2].c_str(), player_names[3].c_str()); myswprintf(infobuf, L"%ls\n%ls\n===VS===\n%ls\n%ls\n", player_names[0].c_str(), player_names[1].c_str(), player_names[2].c_str(), player_names[3].c_str());
else else
myswprintf(infobuf, L"%ls\n===VS===\n%ls\n", player_names[0].c_str(), player_names[1].c_str()); myswprintf(infobuf, L"%ls\n===VS===\n%ls\n", player_names[0].c_str(), player_names[1].c_str());
......
...@@ -284,7 +284,7 @@ public: ...@@ -284,7 +284,7 @@ public:
#define STOC_LEAVE_GAME 0x14 // reserved #define STOC_LEAVE_GAME 0x14 // reserved
#define STOC_DUEL_START 0x15 // no data #define STOC_DUEL_START 0x15 // no data
#define STOC_DUEL_END 0x16 // no data #define STOC_DUEL_END 0x16 // no data
#define STOC_REPLAY 0x17 // ReplayHeader + byte array #define STOC_REPLAY 0x17 // ExtendedReplayHeader + byte array
#define STOC_TIME_LIMIT 0x18 // STOC_TimeLimit #define STOC_TIME_LIMIT 0x18 // STOC_TimeLimit
#define STOC_CHAT 0x19 // uint16_t + uint16_t array #define STOC_CHAT 0x19 // uint16_t + uint16_t array
#define STOC_HS_PLAYER_ENTER 0x20 // STOC_HS_PlayerEnter #define STOC_HS_PLAYER_ENTER 0x20 // STOC_HS_PlayerEnter
......
...@@ -62,7 +62,7 @@ void Replay::BeginRecord() { ...@@ -62,7 +62,7 @@ void Replay::BeginRecord() {
Reset(); Reset();
is_recording = true; is_recording = true;
} }
void Replay::WriteHeader(ReplayHeader& header) { void Replay::WriteHeader(ExtendedReplayHeader& header) {
pheader = header; pheader = header;
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
if(!(replay_mode & REPLAY_MODE_SAVE_IN_SERVER)) return; if(!(replay_mode & REPLAY_MODE_SAVE_IN_SERVER)) return;
...@@ -122,11 +122,11 @@ void Replay::EndRecord() { ...@@ -122,11 +122,11 @@ void Replay::EndRecord() {
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
} }
#endif #endif
pheader.datasize = replay_size; pheader.base.datasize = replay_size;
pheader.flag |= REPLAY_COMPRESSED; pheader.base.flag |= REPLAY_COMPRESSED;
size_t propsize = 5; size_t propsize = 5;
comp_size = MAX_COMP_SIZE; comp_size = MAX_COMP_SIZE;
int ret = LzmaCompress(comp_data, &comp_size, replay_data, replay_size, pheader.props, &propsize, 5, 0x1U << 24, 3, 0, 2, 32, 1); int ret = LzmaCompress(comp_data, &comp_size, replay_data, replay_size, pheader.base.props, &propsize, 5, 0x1U << 24, 3, 0, 2, 32, 1);
if (ret != SZ_OK) { if (ret != SZ_OK) {
std::memcpy(comp_data, &ret, sizeof ret); std::memcpy(comp_data, &ret, sizeof ret);
comp_size = sizeof ret; comp_size = sizeof ret;
...@@ -157,27 +157,31 @@ bool Replay::OpenReplay(const wchar_t* name) { ...@@ -157,27 +157,31 @@ bool Replay::OpenReplay(const wchar_t* name) {
Reset(); Reset();
bool correct_header = true; bool correct_header = true;
if (std::fread(&pheader, sizeof pheader, 1, rfp) < 1) if (std::fread(&pheader, sizeof pheader.base, 1, rfp) < 1)
correct_header = false; correct_header = false;
else if (pheader.id != 0x31707279) else if (pheader.base.id != REPLAY_ID_YRP1 && pheader.base.id != REPLAY_ID_YRP2)
correct_header = false; correct_header = false;
else if (pheader.version < 0x12d0u) else if (pheader.base.version < 0x12d0u)
correct_header = false; correct_header = false;
else if (pheader.version >= 0x1353u && !(pheader.flag & REPLAY_UNIFORM)) else if (pheader.base.version >= 0x1353u && !(pheader.base.flag & REPLAY_UNIFORM))
correct_header = false; correct_header = false;
if (!correct_header) { if (!correct_header) {
std::fclose(rfp); std::fclose(rfp);
return false; return false;
} }
if(pheader.flag & REPLAY_COMPRESSED) { if (pheader.base.id == REPLAY_ID_YRP2 && std::fread(&pheader.seed_sequence, sizeof pheader.seed_sequence, 1, rfp) < 1) {
std::fclose(rfp);
return false;
}
if(pheader.base.flag & REPLAY_COMPRESSED) {
comp_size = std::fread(comp_data, 1, MAX_COMP_SIZE, rfp); comp_size = std::fread(comp_data, 1, MAX_COMP_SIZE, rfp);
std::fclose(rfp); std::fclose(rfp);
if (pheader.datasize > MAX_REPLAY_SIZE) if (pheader.base.datasize > MAX_REPLAY_SIZE)
return false; return false;
replay_size = pheader.datasize; replay_size = pheader.base.datasize;
if (LzmaUncompress(replay_data, &replay_size, comp_data, &comp_size, pheader.props, 5) != SZ_OK) if (LzmaUncompress(replay_data, &replay_size, comp_data, &comp_size, pheader.base.props, 5) != SZ_OK)
return false; return false;
if (replay_size != pheader.datasize) { if (replay_size != pheader.base.datasize) {
replay_size = 0; replay_size = 0;
return false; return false;
} }
...@@ -234,7 +238,7 @@ bool Replay::ReadName(wchar_t* data) { ...@@ -234,7 +238,7 @@ bool Replay::ReadName(wchar_t* data) {
BufferIO::CopyWStr(buffer, data, 20); BufferIO::CopyWStr(buffer, data, 20);
return true; return true;
} }
void Replay::ReadHeader(ReplayHeader& header) { void Replay::ReadHeader(ExtendedReplayHeader& header) {
header = pheader; header = pheader;
} }
bool Replay::ReadData(void* data, size_t length) { bool Replay::ReadData(void* data, size_t length) {
...@@ -277,7 +281,7 @@ bool Replay::IsReplaying() const { ...@@ -277,7 +281,7 @@ bool Replay::IsReplaying() const {
return is_replaying; return is_replaying;
} }
bool Replay::ReadInfo() { bool Replay::ReadInfo() {
int player_count = (pheader.flag & REPLAY_TAG) ? 4 : 2; int player_count = (pheader.base.flag & REPLAY_TAG) ? 4 : 2;
for (int i = 0; i < player_count; ++i) { for (int i = 0; i < player_count; ++i) {
wchar_t name[20]{}; wchar_t name[20]{};
if (!ReadName(name)) if (!ReadName(name))
...@@ -286,11 +290,11 @@ bool Replay::ReadInfo() { ...@@ -286,11 +290,11 @@ bool Replay::ReadInfo() {
} }
if (!ReadData(&params, sizeof params)) if (!ReadData(&params, sizeof params))
return false; return false;
bool is_tag1 = pheader.flag & REPLAY_TAG; bool is_tag1 = pheader.base.flag & REPLAY_TAG;
bool is_tag2 = params.duel_flag & DUEL_TAG_MODE; bool is_tag2 = params.duel_flag & DUEL_TAG_MODE;
if (is_tag1 != is_tag2) if (is_tag1 != is_tag2)
return false; return false;
if (pheader.flag & REPLAY_SINGLE_MODE) { if (pheader.base.flag & REPLAY_SINGLE_MODE) {
uint16_t slen = Read<uint16_t>(); uint16_t slen = Read<uint16_t>();
char filename[256]{}; char filename[256]{};
if (slen == 0 || slen > sizeof(filename) - 1) if (slen == 0 || slen > sizeof(filename) - 1)
......
...@@ -13,6 +13,9 @@ namespace ygo { ...@@ -13,6 +13,9 @@ namespace ygo {
#define REPLAY_SINGLE_MODE 0x8 #define REPLAY_SINGLE_MODE 0x8
#define REPLAY_UNIFORM 0x10 #define REPLAY_UNIFORM 0x10
#define REPLAY_ID_YRP1 0x31707279
#define REPLAY_ID_YRP2 0x32707279
// max size // max size
constexpr int MAX_REPLAY_SIZE = 0x80000; constexpr int MAX_REPLAY_SIZE = 0x80000;
constexpr int MAX_COMP_SIZE = UINT16_MAX + 1; constexpr int MAX_COMP_SIZE = UINT16_MAX + 1;
...@@ -33,6 +36,15 @@ struct ReplayHeader { ...@@ -33,6 +36,15 @@ struct ReplayHeader {
uint8_t props[8]{}; uint8_t props[8]{};
}; };
struct ExtendedReplayHeader {
ReplayHeader base;
uint32_t seed_sequence[SEED_COUNT]{};
uint32_t header_version{ 1 };
uint32_t value1{};
uint32_t value2{};
uint32_t value3{};
};
struct DuelParameters { struct DuelParameters {
int32_t start_lp{}; int32_t start_lp{};
int32_t start_hand{}; int32_t start_hand{};
...@@ -47,7 +59,7 @@ public: ...@@ -47,7 +59,7 @@ public:
// record // record
void BeginRecord(); void BeginRecord();
void WriteHeader(ReplayHeader& header); void WriteHeader(ExtendedReplayHeader& header);
void WriteData(const void* data, size_t length, bool flush = true); void WriteData(const void* data, size_t length, bool flush = true);
template<typename T> template<typename T>
void Write(T data, bool flush = true) { void Write(T data, bool flush = true) {
...@@ -74,7 +86,7 @@ public: ...@@ -74,7 +86,7 @@ public:
bool OpenReplay(const wchar_t* name); bool OpenReplay(const wchar_t* name);
bool ReadNextResponse(unsigned char resp[]); bool ReadNextResponse(unsigned char resp[]);
bool ReadName(wchar_t* data); bool ReadName(wchar_t* data);
void ReadHeader(ReplayHeader& header); void ReadHeader(ExtendedReplayHeader& header);
bool ReadData(void* data, size_t length); bool ReadData(void* data, size_t length);
template<typename T> template<typename T>
T Read() { T Read() {
...@@ -93,7 +105,7 @@ public: ...@@ -93,7 +105,7 @@ public:
HANDLE recording_fp{ nullptr }; HANDLE recording_fp{ nullptr };
#endif #endif
ReplayHeader pheader; ExtendedReplayHeader pheader;
unsigned char* comp_data; unsigned char* comp_data;
size_t comp_size{}; size_t comp_size{};
......
...@@ -57,7 +57,7 @@ bool ReplayMode::ReadReplayResponse() { ...@@ -57,7 +57,7 @@ bool ReplayMode::ReadReplayResponse() {
return result; return result;
} }
int ReplayMode::ReplayThread() { int ReplayMode::ReplayThread() {
const ReplayHeader& rh = cur_replay.pheader; const auto& rh = cur_replay.pheader.base;
mainGame->dInfo.Clear(); mainGame->dInfo.Clear();
mainGame->dInfo.isFirst = true; mainGame->dInfo.isFirst = true;
mainGame->dInfo.isTag = !!(rh.flag & REPLAY_TAG); mainGame->dInfo.isTag = !!(rh.flag & REPLAY_TAG);
...@@ -155,9 +155,7 @@ int ReplayMode::ReplayThread() { ...@@ -155,9 +155,7 @@ int ReplayMode::ReplayThread() {
return 0; return 0;
} }
bool ReplayMode::StartDuel() { bool ReplayMode::StartDuel() {
const ReplayHeader& rh = cur_replay.pheader; const auto& rh = cur_replay.pheader.base;
unsigned int seed = rh.seed;
std::mt19937 rnd(seed);
cur_replay.SkipInfo(); cur_replay.SkipInfo();
if(rh.flag & REPLAY_TAG) { if(rh.flag & REPLAY_TAG) {
BufferIO::CopyWideString(cur_replay.players[0].c_str(), mainGame->dInfo.hostname); BufferIO::CopyWideString(cur_replay.players[0].c_str(), mainGame->dInfo.hostname);
...@@ -168,7 +166,12 @@ bool ReplayMode::StartDuel() { ...@@ -168,7 +166,12 @@ bool ReplayMode::StartDuel() {
BufferIO::CopyWideString(cur_replay.players[0].c_str(), mainGame->dInfo.hostname); BufferIO::CopyWideString(cur_replay.players[0].c_str(), mainGame->dInfo.hostname);
BufferIO::CopyWideString(cur_replay.players[1].c_str(), mainGame->dInfo.clientname); BufferIO::CopyWideString(cur_replay.players[1].c_str(), mainGame->dInfo.clientname);
} }
pduel = create_duel(rnd()); if(rh.id == REPLAY_ID_YRP1) {
std::mt19937 rnd(rh.seed);
pduel = create_duel(rnd());
} else {
pduel = create_duel_v2(cur_replay.pheader.seed_sequence);
}
mainGame->dInfo.duel_rule = cur_replay.params.duel_flag >> 16; mainGame->dInfo.duel_rule = cur_replay.params.duel_flag >> 16;
set_player_info(pduel, 0, cur_replay.params.start_lp, cur_replay.params.start_hand, cur_replay.params.draw_count); set_player_info(pduel, 0, cur_replay.params.start_lp, cur_replay.params.start_hand, cur_replay.params.draw_count);
set_player_info(pduel, 1, cur_replay.params.start_lp, cur_replay.params.start_hand, cur_replay.params.draw_count); set_player_info(pduel, 1, cur_replay.params.start_lp, cur_replay.params.start_hand, cur_replay.params.draw_count);
...@@ -214,8 +217,6 @@ bool ReplayMode::StartDuel() { ...@@ -214,8 +217,6 @@ bool ReplayMode::StartDuel() {
return false; return false;
} }
} }
if (!(rh.flag & REPLAY_UNIFORM))
cur_replay.params.duel_flag |= DUEL_OLD_REPLAY;
start_duel(pduel, cur_replay.params.duel_flag); start_duel(pduel, cur_replay.params.duel_flag);
return true; return true;
} }
......
...@@ -535,20 +535,19 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -535,20 +535,19 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
} }
dp->state = CTOS_RESPONSE; dp->state = CTOS_RESPONSE;
std::random_device rd; std::random_device rd;
unsigned int seed = rd(); ExtendedReplayHeader rh;
#ifdef YGOPRO_SERVER_MODE rh.base.id = REPLAY_ID_YRP2;
if(pre_seed[duel_count] > 0) { rh.base.version = PRO_VERSION;
seed = pre_seed[duel_count]; rh.base.flag = REPLAY_UNIFORM;
} rh.base.start_time = (uint32_t)std::time(nullptr);
#ifdef YGOPRO_SERVER_MODE
if(pre_seed_specified[duel_count])
memcpy(rh.seed_sequence, pre_seed[duel_count], SEED_COUNT * sizeof(uint32_t));
else
#endif #endif
mt19937 rnd((uint_fast32_t)seed); for (auto& x : rh.seed_sequence)
auto duel_seed = rnd.rand(); x = rd();
ReplayHeader rh; mtrandom rnd(rh.seed_sequence, SEED_COUNT);
rh.id = 0x31707279;
rh.version = PRO_VERSION;
rh.flag = REPLAY_UNIFORM;
rh.seed = seed;
rh.start_time = (unsigned int)std::time(nullptr);
last_replay.BeginRecord(); last_replay.BeginRecord();
last_replay.WriteHeader(rh); last_replay.WriteHeader(rh);
last_replay.WriteData(players[0]->name, 40, false); last_replay.WriteData(players[0]->name, 40, false);
...@@ -562,7 +561,7 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -562,7 +561,7 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
set_script_reader(DataManager::ScriptReaderEx); set_script_reader(DataManager::ScriptReaderEx);
set_card_reader(DataManager::CardReader); set_card_reader(DataManager::CardReader);
set_message_handler(SingleDuel::MessageHandler); set_message_handler(SingleDuel::MessageHandler);
pduel = create_duel(duel_seed); pduel = create_duel_v2(rh.seed_sequence);
set_player_info(pduel, 0, host_info.start_lp, host_info.start_hand, host_info.draw_count); set_player_info(pduel, 0, host_info.start_lp, host_info.start_hand, host_info.draw_count);
set_player_info(pduel, 1, host_info.start_lp, host_info.start_hand, host_info.draw_count); set_player_info(pduel, 1, host_info.start_lp, host_info.start_hand, host_info.draw_count);
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
...@@ -1796,10 +1795,10 @@ void SingleDuel::EndDuel() { ...@@ -1796,10 +1795,10 @@ void SingleDuel::EndDuel() {
return; return;
last_replay.EndRecord(); last_replay.EndRecord();
char replaybuf[0x2000], *pbuf = replaybuf; char replaybuf[0x2000], *pbuf = replaybuf;
std::memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader)); std::memcpy(pbuf, &last_replay.pheader, sizeof last_replay.pheader);
pbuf += sizeof(ReplayHeader); pbuf += sizeof last_replay.pheader;
std::memcpy(pbuf, last_replay.comp_data, last_replay.comp_size); std::memcpy(pbuf, last_replay.comp_data, last_replay.comp_size);
NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size); NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof last_replay.pheader + last_replay.comp_size);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
if(!(replay_mode & REPLAY_MODE_WATCHER_NO_SEND)) { if(!(replay_mode & REPLAY_MODE_WATCHER_NO_SEND)) {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include "duelclient.h" #include "duelclient.h"
#include "game.h" #include "game.h"
#include "data_manager.h" #include "data_manager.h"
#include "../ocgcore/mtrandom.h" #include <random>
#include <thread> #include <thread>
namespace ygo { namespace ygo {
...@@ -36,12 +36,22 @@ int SingleMode::SinglePlayThread() { ...@@ -36,12 +36,22 @@ int SingleMode::SinglePlayThread() {
mainGame->dInfo.Clear(); mainGame->dInfo.Clear();
int opt = 0; int opt = 0;
std::random_device rd; std::random_device rd;
unsigned int seed = rd(); ExtendedReplayHeader rh;
mt19937 rnd((uint_fast32_t)seed); rh.base.id = REPLAY_ID_YRP2;
rh.base.version = PRO_VERSION;
rh.base.flag = REPLAY_UNIFORM | REPLAY_SINGLE_MODE;
rh.base.start_time = (uint32_t)std::time(nullptr);
for (auto& x : rh.seed_sequence)
x = rd();
std::seed_seq seed(rh.seed_sequence, rh.seed_sequence + SEED_COUNT);
std::mt19937 rnd(seed);
uint32_t duel_seed[SEED_COUNT]{};
for (auto& x : duel_seed)
x = rnd();
set_script_reader(DataManager::ScriptReaderEx); set_script_reader(DataManager::ScriptReaderEx);
set_card_reader(DataManager::CardReader); set_card_reader(DataManager::CardReader);
set_message_handler(SingleMode::MessageHandler); set_message_handler(SingleMode::MessageHandler);
pduel = create_duel(rnd.rand()); pduel = create_duel_v2(duel_seed);
set_player_info(pduel, 0, start_lp, start_hand, draw_count); set_player_info(pduel, 0, start_lp, start_hand, draw_count);
set_player_info(pduel, 1, start_lp, start_hand, draw_count); set_player_info(pduel, 1, start_lp, start_hand, draw_count);
mainGame->dInfo.lp[0] = start_lp; mainGame->dInfo.lp[0] = start_lp;
...@@ -79,12 +89,6 @@ int SingleMode::SinglePlayThread() { ...@@ -79,12 +89,6 @@ int SingleMode::SinglePlayThread() {
end_duel(pduel); end_duel(pduel);
return 0; return 0;
} }
ReplayHeader rh;
rh.id = 0x31707279;
rh.version = PRO_VERSION;
rh.flag = REPLAY_UNIFORM | REPLAY_SINGLE_MODE;
rh.seed = seed;
rh.start_time = (unsigned int)std::time(nullptr);
mainGame->gMutex.lock(); mainGame->gMutex.lock();
mainGame->HideElement(mainGame->wSinglePlay); mainGame->HideElement(mainGame->wSinglePlay);
mainGame->ClearCardInfo(); mainGame->ClearCardInfo();
......
...@@ -511,20 +511,19 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -511,20 +511,19 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
cur_player[1] = players[3]; cur_player[1] = players[3];
dp->state = CTOS_RESPONSE; dp->state = CTOS_RESPONSE;
std::random_device rd; std::random_device rd;
unsigned int seed = rd(); ExtendedReplayHeader rh;
#ifdef YGOPRO_SERVER_MODE rh.base.id = REPLAY_ID_YRP2;
if(pre_seed[0] > 0) { rh.base.version = PRO_VERSION;
seed = pre_seed[0]; rh.base.flag = REPLAY_UNIFORM | REPLAY_TAG;
} rh.base.start_time = (uint32_t)std::time(nullptr);
#ifdef YGOPRO_SERVER_MODE
if(pre_seed_specified[duel_count])
memcpy(rh.seed_sequence, pre_seed[duel_count], SEED_COUNT * sizeof(uint32_t));
else
#endif #endif
mt19937 rnd((uint_fast32_t)seed); for (auto& x : rh.seed_sequence)
auto duel_seed = rnd.rand(); x = rd();
ReplayHeader rh; mtrandom rnd(rh.seed_sequence, SEED_COUNT);
rh.id = 0x31707279;
rh.version = PRO_VERSION;
rh.flag = REPLAY_UNIFORM | REPLAY_TAG;
rh.seed = seed;
rh.start_time = (unsigned int)std::time(nullptr);
last_replay.BeginRecord(); last_replay.BeginRecord();
last_replay.WriteHeader(rh); last_replay.WriteHeader(rh);
last_replay.WriteData(players[0]->name, 40, false); last_replay.WriteData(players[0]->name, 40, false);
...@@ -542,7 +541,7 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -542,7 +541,7 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
set_script_reader(DataManager::ScriptReaderEx); set_script_reader(DataManager::ScriptReaderEx);
set_card_reader(DataManager::CardReader); set_card_reader(DataManager::CardReader);
set_message_handler(TagDuel::MessageHandler); set_message_handler(TagDuel::MessageHandler);
pduel = create_duel(duel_seed); pduel = create_duel_v2(rh.seed_sequence);
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
preload_script(pduel, "./script/special.lua"); preload_script(pduel, "./script/special.lua");
#endif #endif
...@@ -1887,10 +1886,10 @@ void TagDuel::EndDuel() { ...@@ -1887,10 +1886,10 @@ void TagDuel::EndDuel() {
return; return;
last_replay.EndRecord(); last_replay.EndRecord();
char replaybuf[0x2000], *pbuf = replaybuf; char replaybuf[0x2000], *pbuf = replaybuf;
std::memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader)); std::memcpy(pbuf, &last_replay.pheader, sizeof last_replay.pheader);
pbuf += sizeof(ReplayHeader); pbuf += sizeof last_replay.pheader;
std::memcpy(pbuf, last_replay.comp_data, last_replay.comp_size); std::memcpy(pbuf, last_replay.comp_data, last_replay.comp_size);
NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size); NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof last_replay.pheader + last_replay.comp_size);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
NetServer::ReSendToPlayer(players[2]); NetServer::ReSendToPlayer(players[2]);
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
......
...@@ -324,17 +324,9 @@ if os.istarget("macosx") then ...@@ -324,17 +324,9 @@ if os.istarget("macosx") then
if GetParam("mac-intel") then if GetParam("mac-intel") then
MAC_INTEL = true MAC_INTEL = true
end end
if MAC_ARM or (not MAC_INTEL and os.hostarch() == "ARM64") then
if MAC_ARM then -- building on ARM CPU will target ARM automatically
TARGET_MAC_ARM = true TARGET_MAC_ARM = true
elseif not MAC_INTEL then
-- automatic target arm64, need extra detect
local uname = os.outputof("uname -m")
local proctranslated = os.outputof("sysctl sysctl.proc_translated")
if uname:find("arm") or proctranslated then
print("Detected Apple Silicon Mac")
TARGET_MAC_ARM = true
end
end end
end end
...@@ -407,11 +399,7 @@ workspace "YGOPro" ...@@ -407,11 +399,7 @@ workspace "YGOPro"
targetdir "bin/debug/x64" targetdir "bin/debug/x64"
filter { "configurations:Release", "action:vs*" } filter { "configurations:Release", "action:vs*" }
if linktimeoptimization then linktimeoptimization "On"
linktimeoptimization "On"
else
flags { "LinkTimeOptimization" }
end
staticruntime "On" staticruntime "On"
disablewarnings { "4244", "4267", "4838", "4996", "6011", "6031", "6054", "6262" } disablewarnings { "4244", "4267", "4838", "4996", "6011", "6031", "6054", "6262" }
......
...@@ -493,6 +493,9 @@ ...@@ -493,6 +493,9 @@
!system 1475 已存在同名卡组 !system 1475 已存在同名卡组
!system 1476 删除失败 !system 1476 删除失败
!system 1477 卡片数: !system 1477 卡片数:
!system 1478 导入卡组码
!system 1479 导出卡组码
!system 1480 已导出到剪贴板
!system 1481 OCG !system 1481 OCG
!system 1482 TCG !system 1482 TCG
!system 1483 简体中文 !system 1483 简体中文
......
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