Commit f2f9be5a authored by wind2009's avatar wind2009

Merge remote-tracking branch 'upstream/master'

parents 495485f2 b824c77e
...@@ -59,7 +59,6 @@ Xyz materials: ...@@ -59,7 +59,6 @@ Xyz materials:
### Directories: ### Directories:
* pics: .jpg card images(177*254). * pics: .jpg card images(177*254).
* pics\thumbnail: .jpg thumbnail images(44*64).
* script: .lua script files. * script: .lua script files.
* textures: Other image files. * textures: Other image files.
* deck: .ydk deck files. * deck: .ydk deck files.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <cwchar> #include <cwchar>
#include <vector>
class BufferIO { class BufferIO {
public: public:
...@@ -15,11 +16,21 @@ public: ...@@ -15,11 +16,21 @@ public:
return ret; return ret;
} }
template<typename T> template<typename T>
static void Write(unsigned char*& p, T value) { static void Write(unsigned char*& p, const T& value) {
std::memcpy(p, &value, sizeof(T)); std::memcpy(p, &value, sizeof(T));
p += sizeof(T); p += sizeof(T);
} }
static void VectorWriteBlock(std::vector<unsigned char>& buffer, const void* src, size_t size) {
const auto len = buffer.size();
buffer.resize(len + size);
std::memcpy(buffer.data() + len, src, size);
}
template<typename T>
static void VectorWrite(std::vector<unsigned char>& buffer, const T& value) {
VectorWriteBlock(buffer, &value, sizeof(T));
}
// for compatibility // for compatibility
[[deprecated]] [[deprecated]]
static int32_t ReadInt32(unsigned char*& p) { static int32_t ReadInt32(unsigned char*& p) {
......
...@@ -32,14 +32,15 @@ ClientCard::~ClientCard() { ...@@ -32,14 +32,15 @@ ClientCard::~ClientCard() {
overlayed.clear(); overlayed.clear();
} }
void ClientCard::SetCode(unsigned int x) { void ClientCard::SetCode(unsigned int x) {
if((location == LOCATION_HAND) && (code != x)) { if (code == x) {
code = x; return;
}
if (x == 0) {
chain_code = code;
}
code = x;
if (location == LOCATION_HAND) {
mainGame->dField.MoveCard(this, 5); mainGame->dField.MoveCard(this, 5);
} else {
if (x == 0 && code != 0) {
chain_code = code;
}
code = x;
} }
} }
void ClientCard::UpdateInfo(unsigned char* buf) { void ClientCard::UpdateInfo(unsigned char* buf) {
......
...@@ -456,17 +456,15 @@ void ClientField::ShowSelectCard(bool buttonok, bool is_continuous) { ...@@ -456,17 +456,15 @@ void ClientField::ShowSelectCard(bool buttonok, bool is_continuous) {
if(mainGame->dInfo.curMsg != MSG_SORT_CARD) { if(mainGame->dInfo.curMsg != MSG_SORT_CARD) {
// text // text
wchar_t formatBuffer[2048]; wchar_t formatBuffer[2048];
if(select_continuous) if (select_continuous)
myswprintf(formatBuffer, L"%ls", dataManager.unknown_string); myswprintf(formatBuffer, L"%ls", dataManager.unknown_string);
else if(cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE) else if (cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE)
myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0)); myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0));
else if(selectable_cards[i]->location == LOCATION_OVERLAY) else if (selectable_cards[i]->location == LOCATION_OVERLAY)
myswprintf(formatBuffer, L"%ls[%d](%d)", myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(selectable_cards[i]->overlayTarget->location, selectable_cards[i]->overlayTarget->sequence), dataManager.FormatLocation(selectable_cards[i]->overlayTarget), selectable_cards[i]->overlayTarget->sequence + 1, selectable_cards[i]->sequence + 1);
selectable_cards[i]->overlayTarget->sequence + 1, selectable_cards[i]->sequence + 1);
else else
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i]->location, selectable_cards[i]->sequence), myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i]), selectable_cards[i]->sequence + 1);
selectable_cards[i]->sequence + 1);
mainGame->stCardPos[i]->setText(formatBuffer); mainGame->stCardPos[i]->setText(formatBuffer);
// color // color
if (selectable_cards[i]->is_selected) if (selectable_cards[i]->is_selected)
...@@ -542,8 +540,7 @@ void ClientField::ShowChainCard() { ...@@ -542,8 +540,7 @@ void ClientField::ShowChainCard() {
mainGame->btnCardSelect[i]->setPressed(false); mainGame->btnCardSelect[i]->setPressed(false);
mainGame->btnCardSelect[i]->setVisible(true); mainGame->btnCardSelect[i]->setVisible(true);
wchar_t formatBuffer[2048]; wchar_t formatBuffer[2048];
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i]->location, selectable_cards[i]->sequence), myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i]), selectable_cards[i]->sequence + 1);
selectable_cards[i]->sequence + 1);
mainGame->stCardPos[i]->setText(formatBuffer); mainGame->stCardPos[i]->setText(formatBuffer);
if(selectable_cards[i]->location == LOCATION_OVERLAY) { if(selectable_cards[i]->location == LOCATION_OVERLAY) {
if(selectable_cards[i]->owner != selectable_cards[i]->overlayTarget->controler) if(selectable_cards[i]->owner != selectable_cards[i]->overlayTarget->controler)
...@@ -597,13 +594,11 @@ void ClientField::ShowLocationCard() { ...@@ -597,13 +594,11 @@ void ClientField::ShowLocationCard() {
mainGame->btnCardDisplay[i]->setPressed(false); mainGame->btnCardDisplay[i]->setPressed(false);
mainGame->btnCardDisplay[i]->setVisible(true); mainGame->btnCardDisplay[i]->setVisible(true);
wchar_t formatBuffer[2048]; wchar_t formatBuffer[2048];
if(display_cards[i]->location == LOCATION_OVERLAY) if (display_cards[i]->location == LOCATION_OVERLAY)
myswprintf(formatBuffer, L"%ls[%d](%d)", myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(display_cards[i]->overlayTarget->location, display_cards[i]->overlayTarget->sequence), dataManager.FormatLocation(display_cards[i]->overlayTarget), display_cards[i]->overlayTarget->sequence + 1, display_cards[i]->sequence + 1);
display_cards[i]->overlayTarget->sequence + 1, display_cards[i]->sequence + 1);
else else
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(display_cards[i]->location, display_cards[i]->sequence), myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(display_cards[i]), display_cards[i]->sequence + 1);
display_cards[i]->sequence + 1);
mainGame->stDisplayPos[i]->setText(formatBuffer); mainGame->stDisplayPos[i]->setText(formatBuffer);
if(display_cards[i]->location == LOCATION_OVERLAY) { if(display_cards[i]->location == LOCATION_OVERLAY) {
if(display_cards[i]->owner != display_cards[i]->overlayTarget->controler) if(display_cards[i]->owner != display_cards[i]->overlayTarget->controler)
......
#include "data_manager.h" #include "data_manager.h"
#include "game.h" #include "game.h"
#include "client_card.h"
#include "spmemvfs/spmemvfs.h" #include "spmemvfs/spmemvfs.h"
namespace ygo { namespace ygo {
...@@ -220,34 +221,26 @@ const wchar_t* DataManager::GetDesc(uint32_t strCode) const { ...@@ -220,34 +221,26 @@ const wchar_t* DataManager::GetDesc(uint32_t strCode) const {
return csit->second.desc[offset].c_str(); return csit->second.desc[offset].c_str();
return unknown_string; return unknown_string;
} }
const wchar_t* DataManager::GetSysString(int code) const { const wchar_t* DataManager::GetMapString(const wstring_map& table, uint32_t code) const {
if (code < 0 || code > MAX_STRING_ID) auto csit = table.find(code);
return unknown_string; if (csit == table.end())
auto csit = _sysStrings.find(code);
if(csit == _sysStrings.end())
return unknown_string; return unknown_string;
return csit->second.c_str(); return csit->second.c_str();
} }
const wchar_t* DataManager::GetVictoryString(int code) const { const wchar_t* DataManager::GetSysString(uint32_t code) const {
auto csit = _victoryStrings.find(code); return GetMapString(_sysStrings, code);
if(csit == _victoryStrings.end())
return unknown_string;
return csit->second.c_str();
} }
const wchar_t* DataManager::GetCounterName(int code) const { const wchar_t* DataManager::GetVictoryString(uint32_t code) const {
auto csit = _counterStrings.find(code); return GetMapString(_victoryStrings, code);
if(csit == _counterStrings.end())
return unknown_string;
return csit->second.c_str();
} }
const wchar_t* DataManager::GetSetName(int code) const { const wchar_t* DataManager::GetCounterName(uint32_t code) const {
auto csit = _setnameStrings.find(code); return GetMapString(_counterStrings, code);
if(csit == _setnameStrings.end()) }
return unknown_string; const wchar_t* DataManager::GetSetName(uint32_t code) const {
return csit->second.c_str(); return GetMapString(_setnameStrings, code);
} }
std::vector<unsigned int> DataManager::GetSetCodes(std::wstring setname) const { std::vector<uint32_t> DataManager::GetSetCodes(std::wstring setname) const {
std::vector<unsigned int> matchingCodes; std::vector<uint32_t> matchingCodes;
for(auto csit = _setnameStrings.begin(); csit != _setnameStrings.end(); ++csit) { for(auto csit = _setnameStrings.begin(); csit != _setnameStrings.end(); ++csit) {
auto xpos = csit->second.find_first_of(L'|');//setname|another setname or extra info auto xpos = csit->second.find_first_of(L'|');//setname|another setname or extra info
if(setname.size() < 2) { if(setname.size() < 2) {
...@@ -280,11 +273,10 @@ const wchar_t* DataManager::FormatLocation(int location, int sequence) const { ...@@ -280,11 +273,10 @@ const wchar_t* DataManager::FormatLocation(int location, int sequence) const {
else else
return GetSysString(1009); return GetSysString(1009);
} }
int i = 1000;
int string_id = 0; int string_id = 0;
for (unsigned filter = LOCATION_DECK; filter <= LOCATION_PZONE; filter <<= 1, ++i) { for (int i = 0; i < 10; ++i) {
if (filter == location) { if ((0x1U << i) == location) {
string_id = i; string_id = STRING_ID_LOCATION + i;
break; break;
} }
} }
...@@ -293,6 +285,11 @@ const wchar_t* DataManager::FormatLocation(int location, int sequence) const { ...@@ -293,6 +285,11 @@ const wchar_t* DataManager::FormatLocation(int location, int sequence) const {
else else
return unknown_string; return unknown_string;
} }
const wchar_t* DataManager::FormatLocation(ClientCard* card) const {
if (!card)
return unknown_string;
return FormatLocation(card->location, card->sequence);
}
std::wstring DataManager::FormatAttribute(unsigned int attribute) const { std::wstring DataManager::FormatAttribute(unsigned int attribute) const {
std::wstring buffer; std::wstring buffer;
for (int i = 0; i < ATTRIBUTES_COUNT; ++i) { for (int i = 0; i < ATTRIBUTES_COUNT; ++i) {
...@@ -303,7 +300,7 @@ std::wstring DataManager::FormatAttribute(unsigned int attribute) const { ...@@ -303,7 +300,7 @@ std::wstring DataManager::FormatAttribute(unsigned int attribute) const {
} }
} }
if (buffer.empty()) if (buffer.empty())
return std::wstring(unknown_string); buffer = unknown_string;
return buffer; return buffer;
} }
std::wstring DataManager::FormatRace(unsigned int race) const { std::wstring DataManager::FormatRace(unsigned int race) const {
...@@ -316,7 +313,7 @@ std::wstring DataManager::FormatRace(unsigned int race) const { ...@@ -316,7 +313,7 @@ std::wstring DataManager::FormatRace(unsigned int race) const {
} }
} }
if (buffer.empty()) if (buffer.empty())
return std::wstring(unknown_string); buffer = unknown_string;
return buffer; return buffer;
} }
std::wstring DataManager::FormatType(unsigned int type) const { std::wstring DataManager::FormatType(unsigned int type) const {
...@@ -329,7 +326,7 @@ std::wstring DataManager::FormatType(unsigned int type) const { ...@@ -329,7 +326,7 @@ std::wstring DataManager::FormatType(unsigned int type) const {
} }
} }
if (buffer.empty()) if (buffer.empty())
return std::wstring(unknown_string); buffer = unknown_string;
return buffer; return buffer;
} }
std::wstring DataManager::FormatSetName(const uint16_t setcode[]) const { std::wstring DataManager::FormatSetName(const uint16_t setcode[]) const {
...@@ -343,7 +340,7 @@ std::wstring DataManager::FormatSetName(const uint16_t setcode[]) const { ...@@ -343,7 +340,7 @@ std::wstring DataManager::FormatSetName(const uint16_t setcode[]) const {
buffer.append(setname); buffer.append(setname);
} }
if (buffer.empty()) if (buffer.empty())
return std::wstring(unknown_string); buffer = unknown_string;
return buffer; return buffer;
} }
std::wstring DataManager::FormatLinkMarker(unsigned int link_marker) const { std::wstring DataManager::FormatLinkMarker(unsigned int link_marker) const {
......
...@@ -57,6 +57,9 @@ struct CardString { ...@@ -57,6 +57,9 @@ struct CardString {
}; };
using code_pointer = std::unordered_map<uint32_t, CardDataC>::const_iterator; using code_pointer = std::unordered_map<uint32_t, CardDataC>::const_iterator;
using string_pointer = std::unordered_map<uint32_t, CardString>::const_iterator; using string_pointer = std::unordered_map<uint32_t, CardString>::const_iterator;
using wstring_map = std::unordered_map<uint32_t, std::wstring>;
class ClientCard;
class DataManager { class DataManager {
public: public:
...@@ -81,30 +84,32 @@ public: ...@@ -81,30 +84,32 @@ public:
const wchar_t* GetName(uint32_t code) const; const wchar_t* GetName(uint32_t code) const;
const wchar_t* GetText(uint32_t code) const; const wchar_t* GetText(uint32_t code) const;
const wchar_t* GetDesc(uint32_t strCode) const; const wchar_t* GetDesc(uint32_t strCode) const;
const wchar_t* GetSysString(int code) const; const wchar_t* GetSysString(uint32_t code) const;
const wchar_t* GetVictoryString(int code) const; const wchar_t* GetVictoryString(uint32_t code) const;
const wchar_t* GetCounterName(int code) const; const wchar_t* GetCounterName(uint32_t code) const;
const wchar_t* GetSetName(int code) const; const wchar_t* GetSetName(uint32_t code) const;
std::vector<unsigned int> GetSetCodes(std::wstring setname) const; std::vector<uint32_t> GetSetCodes(std::wstring setname) const;
std::wstring GetNumString(int num, bool bracket = false) const; std::wstring GetNumString(int num, bool bracket = false) const;
const wchar_t* FormatLocation(int location, int sequence) const; const wchar_t* FormatLocation(int location, int sequence) const;
const wchar_t* FormatLocation(ClientCard* card) const;
std::wstring FormatAttribute(unsigned int attribute) const; std::wstring FormatAttribute(unsigned int attribute) const;
std::wstring FormatRace(unsigned int race) const; std::wstring FormatRace(unsigned int race) const;
std::wstring FormatType(unsigned int type) const; std::wstring FormatType(unsigned int type) const;
std::wstring FormatSetName(const uint16_t setcode[]) const; std::wstring FormatSetName(const uint16_t setcode[]) const;
std::wstring FormatLinkMarker(unsigned int link_marker) const; std::wstring FormatLinkMarker(unsigned int link_marker) const;
std::unordered_map<unsigned int, std::wstring> _counterStrings; wstring_map _counterStrings;
std::unordered_map<unsigned int, std::wstring> _victoryStrings; wstring_map _victoryStrings;
std::unordered_map<unsigned int, std::wstring> _setnameStrings; wstring_map _setnameStrings;
std::unordered_map<unsigned int, std::wstring> _sysStrings; wstring_map _sysStrings;
char errmsg[512]{}; char errmsg[512]{};
const wchar_t* unknown_string{ L"???" }; const wchar_t* unknown_string{ L"???" };
irr::io::IFileSystem* FileSystem{}; irr::io::IFileSystem* FileSystem{};
static constexpr int STRING_ID_ATTRIBUTE = 1010; static constexpr uint32_t STRING_ID_LOCATION = 1000;
static constexpr int STRING_ID_RACE = 1020; static constexpr uint32_t STRING_ID_ATTRIBUTE = 1010;
static constexpr int STRING_ID_TYPE = 1050; static constexpr uint32_t STRING_ID_RACE = 1020;
static constexpr uint32_t STRING_ID_TYPE = 1050;
static constexpr int TYPES_COUNT = 27; static constexpr int TYPES_COUNT = 27;
static unsigned char scriptBuffer[0x100000]; static unsigned char scriptBuffer[0x100000];
...@@ -122,6 +127,7 @@ public: ...@@ -122,6 +127,7 @@ public:
static bool deck_sort_name(code_pointer l1, code_pointer l2); static bool deck_sort_name(code_pointer l1, code_pointer l2);
private: private:
const wchar_t* GetMapString(const wstring_map& table, uint32_t code) const;
std::unordered_map<uint32_t, CardDataC> _datas; std::unordered_map<uint32_t, CardDataC> _datas;
std::unordered_map<uint32_t, CardString> _strings; std::unordered_map<uint32_t, CardString> _strings;
std::unordered_map<uint32_t, std::vector<uint16_t>> extra_setcode; std::unordered_map<uint32_t, std::vector<uint16_t>> extra_setcode;
......
...@@ -179,10 +179,12 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -179,10 +179,12 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
std::sort(deckManager.current_deck.main.begin(), deckManager.current_deck.main.end(), DataManager::deck_sort_lv); std::sort(deckManager.current_deck.main.begin(), deckManager.current_deck.main.end(), DataManager::deck_sort_lv);
std::sort(deckManager.current_deck.extra.begin(), deckManager.current_deck.extra.end(), DataManager::deck_sort_lv); std::sort(deckManager.current_deck.extra.begin(), deckManager.current_deck.extra.end(), DataManager::deck_sort_lv);
std::sort(deckManager.current_deck.side.begin(), deckManager.current_deck.side.end(), DataManager::deck_sort_lv); std::sort(deckManager.current_deck.side.begin(), deckManager.current_deck.side.end(), DataManager::deck_sort_lv);
is_modified = true;
break; break;
} }
case BUTTON_SHUFFLE_DECK: { case BUTTON_SHUFFLE_DECK: {
std::shuffle(deckManager.current_deck.main.begin(), deckManager.current_deck.main.end(), rnd); std::shuffle(deckManager.current_deck.main.begin(), deckManager.current_deck.main.end(), rnd);
is_modified = true;
break; break;
} }
case BUTTON_SAVE_DECK: { case BUTTON_SAVE_DECK: {
...@@ -702,17 +704,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -702,17 +704,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
break; break;
} }
mainGame->ClearCardInfo(); mainGame->ClearCardInfo();
unsigned char deckbuf[1024]{}; DuelClient::SendUpdateDeck(deckManager.current_deck);
auto pdeck = deckbuf;
BufferIO::Write<int32_t>(pdeck, static_cast<int32_t>(deckManager.current_deck.main.size() + deckManager.current_deck.extra.size()));
BufferIO::Write<int32_t>(pdeck, static_cast<int32_t>(deckManager.current_deck.side.size()));
for(size_t i = 0; i < deckManager.current_deck.main.size(); ++i)
BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.main[i]->first);
for(size_t i = 0; i < deckManager.current_deck.extra.size(); ++i)
BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.extra[i]->first);
for(size_t i = 0; i < deckManager.current_deck.side.size(); ++i)
BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.side[i]->first);
DuelClient::SendBufferToServer(CTOS_UPDATE_DECK, deckbuf, pdeck - deckbuf);
break; break;
} }
case BUTTON_SIDE_RELOAD: { case BUTTON_SIDE_RELOAD: {
...@@ -750,6 +742,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -750,6 +742,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
deckManager.current_deck.main.clear(); deckManager.current_deck.main.clear();
deckManager.current_deck.extra.clear(); deckManager.current_deck.extra.clear();
deckManager.current_deck.side.clear(); deckManager.current_deck.side.clear();
is_modified = true;
} else if(prev_operation == BUTTON_DELETE_DECK) { } else if(prev_operation == BUTTON_DELETE_DECK) {
int sel = prev_sel; int sel = prev_sel;
mainGame->cbDBDecks->setSelected(sel); mainGame->cbDBDecks->setSelected(sel);
...@@ -1093,6 +1086,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -1093,6 +1086,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
is_starting_dragging = false; is_starting_dragging = false;
irr::gui::IGUIElement* root = mainGame->env->getRootGUIElement(); irr::gui::IGUIElement* root = mainGame->env->getRootGUIElement();
if(!is_draging && !mainGame->is_siding && root->getElementFromPoint(mouse_pos) == mainGame->imgCard) { if(!is_draging && !mainGame->is_siding && root->getElementFromPoint(mouse_pos) == mainGame->imgCard) {
soundManager.PlaySoundEffect(SOUND_CARD_DROP);
ShowBigCard(mainGame->showingcode, 1); ShowBigCard(mainGame->showingcode, 1);
break; break;
} }
...@@ -1122,6 +1116,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -1122,6 +1116,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
case irr::EMIE_LMOUSE_DOUBLE_CLICK: { case irr::EMIE_LMOUSE_DOUBLE_CLICK: {
irr::gui::IGUIElement* root = mainGame->env->getRootGUIElement(); irr::gui::IGUIElement* root = mainGame->env->getRootGUIElement();
if(!is_draging && !mainGame->is_siding && root->getElementFromPoint(mouse_pos) == root && hovered_code) { if(!is_draging && !mainGame->is_siding && root->getElementFromPoint(mouse_pos) == root && hovered_code) {
soundManager.PlaySoundEffect(SOUND_CARD_DROP);
ShowBigCard(hovered_code, 1); ShowBigCard(hovered_code, 1);
break; break;
} }
...@@ -1381,8 +1376,6 @@ void DeckBuilder::GetHoveredCard() { ...@@ -1381,8 +1376,6 @@ void DeckBuilder::GetHoveredCard() {
if(!is_draging && pre_code != hovered_code) { if(!is_draging && pre_code != hovered_code) {
if(hovered_code) if(hovered_code)
mainGame->ShowCardInfo(hovered_code); mainGame->ShowCardInfo(hovered_code);
if(pre_code)
imageManager.RemoveTexture(pre_code);
} }
} }
void DeckBuilder::StartFilter() { void DeckBuilder::StartFilter() {
...@@ -1403,7 +1396,7 @@ void DeckBuilder::FilterCards() { ...@@ -1403,7 +1396,7 @@ void DeckBuilder::FilterCards() {
results.clear(); results.clear();
struct element_t { struct element_t {
std::wstring keyword; std::wstring keyword;
std::vector<unsigned int> setcodes; std::vector<uint32_t> setcodes;
enum class type_t { enum class type_t {
all, all,
name, name,
......
...@@ -829,11 +829,11 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) { ...@@ -829,11 +829,11 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) {
break; break;
} }
case STOC_HS_PLAYER_ENTER: { case STOC_HS_PLAYER_ENTER: {
if (len < 1 + STOC_HS_PlayerEnter_size) if (len < 1 + sizeof(STOC_HS_PlayerEnter))
return; return;
soundManager.PlaySoundEffect(SOUND_PLAYER_ENTER); soundManager.PlaySoundEffect(SOUND_PLAYER_ENTER);
STOC_HS_PlayerEnter packet; STOC_HS_PlayerEnter packet;
std::memcpy(&packet, pdata, STOC_HS_PlayerEnter_size); std::memcpy(&packet, pdata, sizeof(STOC_HS_PlayerEnter));
auto pkt = &packet; auto pkt = &packet;
if(pkt->pos > 3) if(pkt->pos > 3)
break; break;
...@@ -2942,7 +2942,7 @@ bool DuelClient::ClientAnalyze(unsigned char* msg, int len) { ...@@ -2942,7 +2942,7 @@ bool DuelClient::ClientAnalyze(unsigned char* msg, int len) {
pcard->SetCode(code); pcard->SetCode(code);
pcard->position = cp; pcard->position = cp;
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) {
soundManager.PlaySoundEffect(SOUND_FILP); soundManager.PlaySoundEffect(SOUND_FLIP);
myswprintf(event_string, dataManager.GetSysString(1607), dataManager.GetName(code)); myswprintf(event_string, dataManager.GetSysString(1607), dataManager.GetName(code));
mainGame->dField.MoveCard(pcard, 10); mainGame->dField.MoveCard(pcard, 10);
mainGame->WaitFrameSignal(11); mainGame->WaitFrameSignal(11);
...@@ -4067,6 +4067,19 @@ void DuelClient::SendResponse() { ...@@ -4067,6 +4067,19 @@ void DuelClient::SendResponse() {
SendBufferToServer(CTOS_RESPONSE, response_buf, response_len); SendBufferToServer(CTOS_RESPONSE, response_buf, response_len);
} }
} }
void DuelClient::SendUpdateDeck(const Deck& deck) {
std::vector<unsigned char> deckbuf;
deckbuf.reserve(1024);
BufferIO::VectorWrite<int32_t>(deckbuf, static_cast<int32_t>(deck.main.size() + deck.extra.size()));
BufferIO::VectorWrite<int32_t>(deckbuf, static_cast<int32_t>(deck.side.size()));
for (const auto& card: deck.main)
BufferIO::VectorWrite<uint32_t>(deckbuf, card->first);
for (const auto& card: deck.extra)
BufferIO::VectorWrite<uint32_t>(deckbuf, card->first);
for (const auto& card: deck.side)
BufferIO::VectorWrite<uint32_t>(deckbuf, card->first);
SendBufferToServer(CTOS_UPDATE_DECK, deckbuf.data(), deckbuf.size());
}
void DuelClient::BeginRefreshHost() { void DuelClient::BeginRefreshHost() {
if(is_refreshing) if(is_refreshing)
return; return;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <set> #include <set>
#include <random> #include <random>
#include "config.h" #include "config.h"
#include "deck_manager.h"
#include "network.h" #include "network.h"
namespace ygo { namespace ygo {
...@@ -48,6 +49,7 @@ public: ...@@ -48,6 +49,7 @@ public:
static void SetResponseI(int32_t respI); static void SetResponseI(int32_t respI);
static void SetResponseB(void* respB, size_t len); static void SetResponseB(void* respB, size_t len);
static void SendResponse(); static void SendResponse();
static void SendUpdateDeck(const Deck& deck);
static void SendPacketToServer(unsigned char proto) { static void SendPacketToServer(unsigned char proto) {
auto p = duel_client_write; auto p = duel_client_write;
BufferIO::Write<uint16_t>(p, 1); BufferIO::Write<uint16_t>(p, 1);
......
...@@ -905,17 +905,15 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -905,17 +905,15 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
else else
myswprintf(formatBuffer, L""); myswprintf(formatBuffer, L"");
} else { } else {
if(select_continuous) if (select_continuous)
myswprintf(formatBuffer, L"%ls", dataManager.unknown_string); myswprintf(formatBuffer, L"%ls", dataManager.unknown_string);
else if(cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE) else if (cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE)
myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0)); myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0));
else if(selectable_cards[i + pos]->location == LOCATION_OVERLAY) else if (selectable_cards[i + pos]->location == LOCATION_OVERLAY)
myswprintf(formatBuffer, L"%ls[%d](%d)", myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(selectable_cards[i + pos]->overlayTarget->location, selectable_cards[i + pos]->overlayTarget->sequence), dataManager.FormatLocation(selectable_cards[i + pos]->overlayTarget), selectable_cards[i + pos]->overlayTarget->sequence + 1, selectable_cards[i + pos]->sequence + 1);
selectable_cards[i + pos]->overlayTarget->sequence + 1, selectable_cards[i + pos]->sequence + 1);
else else
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i + pos]->location, selectable_cards[i + pos]->sequence), myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i + pos]), selectable_cards[i + pos]->sequence + 1);
selectable_cards[i + pos]->sequence + 1);
} }
mainGame->stCardPos[i]->setText(formatBuffer); mainGame->stCardPos[i]->setText(formatBuffer);
// color // color
...@@ -961,13 +959,11 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -961,13 +959,11 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
mainGame->btnCardDisplay[i]->setImage(imageManager.tCover[display_cards[i + pos]->controler + 2]); mainGame->btnCardDisplay[i]->setImage(imageManager.tCover[display_cards[i + pos]->controler + 2]);
mainGame->btnCardDisplay[i]->setRelativePosition(irr::core::rect<irr::s32>(30 + i * 125, 55, 30 + 120 + i * 125, 225)); mainGame->btnCardDisplay[i]->setRelativePosition(irr::core::rect<irr::s32>(30 + i * 125, 55, 30 + 120 + i * 125, 225));
wchar_t formatBuffer[2048]; wchar_t formatBuffer[2048];
if(display_cards[i + pos]->location == LOCATION_OVERLAY) { if(display_cards[i + pos]->location == LOCATION_OVERLAY)
myswprintf(formatBuffer, L"%ls[%d](%d)", myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(display_cards[i + pos]->overlayTarget->location, display_cards[i + pos]->overlayTarget->sequence), dataManager.FormatLocation(display_cards[i + pos]->overlayTarget), display_cards[i + pos]->overlayTarget->sequence + 1, display_cards[i + pos]->sequence + 1);
display_cards[i + pos]->overlayTarget->sequence + 1, display_cards[i + pos]->sequence + 1); else
} else myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(display_cards[i + pos]), display_cards[i + pos]->sequence + 1);
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(display_cards[i + pos]->location, display_cards[i + pos]->sequence),
display_cards[i + pos]->sequence + 1);
mainGame->stDisplayPos[i]->setText(formatBuffer); mainGame->stDisplayPos[i]->setText(formatBuffer);
if(display_cards[i + pos]->location == LOCATION_OVERLAY) { if(display_cards[i + pos]->location == LOCATION_OVERLAY) {
if(display_cards[i + pos]->owner != display_cards[i + pos]->overlayTarget->controler) if(display_cards[i + pos]->owner != display_cards[i + pos]->overlayTarget->controler)
......
...@@ -1089,16 +1089,13 @@ void Game::InitStaticText(irr::gui::IGUIStaticText* pControl, irr::u32 cWidth, i ...@@ -1089,16 +1089,13 @@ void Game::InitStaticText(irr::gui::IGUIStaticText* pControl, irr::u32 cWidth, i
scrCardText->setPos(0); scrCardText->setPos(0);
} }
std::wstring Game::SetStaticText(irr::gui::IGUIStaticText* pControl, irr::u32 cWidth, irr::gui::CGUITTFont* font, const wchar_t* text, irr::u32 pos) { std::wstring Game::SetStaticText(irr::gui::IGUIStaticText* pControl, irr::u32 cWidth, irr::gui::CGUITTFont* font, const wchar_t* text, irr::u32 pos) {
size_t pbuffer = 0;
irr::u32 _width = 0, _height = 0; irr::u32 _width = 0, _height = 0;
wchar_t prev = 0; wchar_t prev = 0;
wchar_t strBuffer[4096]{}; std::wstring result;
constexpr size_t buffer_len = sizeof strBuffer / sizeof strBuffer[0] - 1; result.reserve(4096);
const size_t text_len = std::wcslen(text); const size_t text_len = std::wcslen(text);
for(size_t i = 0; i < text_len ; ++i) { for(size_t i = 0; i < text_len ; ++i) {
if (pbuffer >= buffer_len)
break;
wchar_t c = text[i]; wchar_t c = text[i];
irr::u32 w = font->getCharDimension(c).Width + font->getKerningWidth(c, prev); irr::u32 w = font->getCharDimension(c).Width + font->getKerningWidth(c, prev);
prev = c; prev = c;
...@@ -1106,31 +1103,28 @@ std::wstring Game::SetStaticText(irr::gui::IGUIStaticText* pControl, irr::u32 cW ...@@ -1106,31 +1103,28 @@ std::wstring Game::SetStaticText(irr::gui::IGUIStaticText* pControl, irr::u32 cW
continue; continue;
} }
if (c == L'\n') { if (c == L'\n') {
strBuffer[pbuffer++] = L'\n'; result.push_back(L'\n');
_width = 0; _width = 0;
_height++; _height++;
prev = 0; prev = 0;
if (_height == pos) if (_height == pos)
pbuffer = 0; result.clear();
continue; continue;
} }
if (_width > 0 && _width + w > cWidth) { if (_width > 0 && _width + w > cWidth) {
strBuffer[pbuffer++] = L'\n'; result.push_back(L'\n');
_width = 0; _width = 0;
_height++; _height++;
prev = 0; prev = 0;
if (_height == pos) if (_height == pos)
pbuffer = 0; result.clear();
} }
if (pbuffer >= buffer_len)
break;
_width += w; _width += w;
strBuffer[pbuffer++] = c; result.push_back(c);
} }
strBuffer[pbuffer] = 0;
if (pControl) if (pControl)
pControl->setText(strBuffer); pControl->setText(result.c_str());
return std::wstring(strBuffer); return result;
} }
void Game::LoadExpansions() { void Game::LoadExpansions() {
FileSystem::TraversalDir(L"./expansions", [](const wchar_t* name, bool isdir) { FileSystem::TraversalDir(L"./expansions", [](const wchar_t* name, bool isdir) {
...@@ -1330,8 +1324,6 @@ void Game::LoadConfig() { ...@@ -1330,8 +1324,6 @@ void Game::LoadConfig() {
gameConf.antialias = std::strtol(valbuf, nullptr, 10); gameConf.antialias = std::strtol(valbuf, nullptr, 10);
} else if(!std::strcmp(strbuf, "use_d3d")) { } else if(!std::strcmp(strbuf, "use_d3d")) {
gameConf.use_d3d = std::strtol(valbuf, nullptr, 10) > 0; gameConf.use_d3d = std::strtol(valbuf, nullptr, 10) > 0;
} else if(!std::strcmp(strbuf, "use_image_scale")) {
gameConf.use_image_scale = std::strtol(valbuf, nullptr, 10) > 0;
} else if (!std::strcmp(strbuf, "use_image_scale_multi_thread")) { } else if (!std::strcmp(strbuf, "use_image_scale_multi_thread")) {
gameConf.use_image_scale_multi_thread = std::strtol(valbuf, nullptr, 10) > 0; gameConf.use_image_scale_multi_thread = std::strtol(valbuf, nullptr, 10) > 0;
} else if (!std::strcmp(strbuf, "use_image_load_background_thread")) { } else if (!std::strcmp(strbuf, "use_image_load_background_thread")) {
...@@ -1466,7 +1458,6 @@ void Game::SaveConfig() { ...@@ -1466,7 +1458,6 @@ void Game::SaveConfig() {
std::fprintf(fp, "#config file\n#nickname & gamename should be less than 20 characters\n"); std::fprintf(fp, "#config file\n#nickname & gamename should be less than 20 characters\n");
char linebuf[CONFIG_LINE_SIZE]; char linebuf[CONFIG_LINE_SIZE];
std::fprintf(fp, "use_d3d = %d\n", gameConf.use_d3d ? 1 : 0); std::fprintf(fp, "use_d3d = %d\n", gameConf.use_d3d ? 1 : 0);
std::fprintf(fp, "use_image_scale = %d\n", gameConf.use_image_scale ? 1 : 0);
std::fprintf(fp, "use_image_scale_multi_thread = %d\n", gameConf.use_image_scale_multi_thread ? 1 : 0); std::fprintf(fp, "use_image_scale_multi_thread = %d\n", gameConf.use_image_scale_multi_thread ? 1 : 0);
std::fprintf(fp, "use_image_load_background_thread = %d\n", gameConf.use_image_load_background_thread ? 1 : 0); std::fprintf(fp, "use_image_load_background_thread = %d\n", gameConf.use_image_load_background_thread ? 1 : 0);
std::fprintf(fp, "antialias = %d\n", gameConf.antialias); std::fprintf(fp, "antialias = %d\n", gameConf.antialias);
......
...@@ -48,7 +48,6 @@ bool IsExtension(const char* filename, const char(&extension)[N]) { ...@@ -48,7 +48,6 @@ bool IsExtension(const char* filename, const char(&extension)[N]) {
struct Config { struct Config {
bool use_d3d{ false }; bool use_d3d{ false };
bool use_image_scale{ true };
bool use_image_scale_multi_thread{ true }; bool use_image_scale_multi_thread{ true };
#ifdef _OPENMP #ifdef _OPENMP
bool use_image_load_background_thread{ false }; bool use_image_load_background_thread{ false };
......
This diff is collapsed.
...@@ -10,13 +10,17 @@ ...@@ -10,13 +10,17 @@
namespace ygo { namespace ygo {
class ImageManager { class ImageManager {
private:
void resizeImage(irr::video::IImage* src, irr::video::IImage* dest, bool use_threading);
irr::video::ITexture* addTexture(const char* name, irr::video::IImage* srcimg, irr::s32 width, irr::s32 height);
public: public:
bool Initial(); bool Initial();
void SetDevice(irr::IrrlichtDevice* dev); void SetDevice(irr::IrrlichtDevice* dev);
void ClearTexture(); void ClearTexture();
void RemoveTexture(int code);
void ResizeTexture(); void ResizeTexture();
irr::video::ITexture* GetTextureFromFile(const char* file, irr::s32 width, irr::s32 height); irr::video::ITexture* GetTextureFromFile(const char* file, irr::s32 width, irr::s32 height);
irr::video::IImage* GetImage(int code);
irr::video::ITexture* GetTexture(int code, irr::s32 width, irr::s32 height);
irr::video::ITexture* GetTexture(int code, bool fit = false); irr::video::ITexture* GetTexture(int code, bool fit = false);
irr::video::ITexture* GetBigPicture(int code, float zoom); irr::video::ITexture* GetBigPicture(int code, float zoom);
irr::video::ITexture* GetTextureThumb(int code); irr::video::ITexture* GetTextureThumb(int code);
......
#include "image_resizer.h"
#include <cmath>
#ifdef _OPENMP
#include <omp.h>
#endif
#define STB_IMAGE_RESIZE2_IMPLEMENTATION
#include "stb_image_resize2.h"
namespace ygo {
ImageResizer imageResizer;
struct StbSamplerCache {
STBIR_RESIZE resize{};
int in_w = 0;
int in_h = 0;
int out_w = 0;
int out_h = 0;
stbir_pixel_layout layout = STBIR_BGRA;
bool samplers_built = false;
~StbSamplerCache() {
if(samplers_built) {
stbir_free_samplers(&resize);
samplers_built = false;
}
}
void reset_if_needed(int new_in_w, int new_in_h, int new_out_w, int new_out_h, stbir_pixel_layout new_layout) {
if(new_in_w == in_w && new_in_h == in_h && new_out_w == out_w && new_out_h == out_h && new_layout == layout)
return;
if(samplers_built) {
stbir_free_samplers(&resize);
samplers_built = false;
}
in_w = new_in_w;
in_h = new_in_h;
out_w = new_out_w;
out_h = new_out_h;
layout = new_layout;
resize = STBIR_RESIZE{};
}
};
/**
* Scale image using stb_image_resize2.
* Returns true on success, false on failure or unsupported format.
*/
bool ImageResizer::imageScaleSTB(irr::video::IImage* src, irr::video::IImage* dest) {
if(!src || !dest)
return false;
const auto srcDim = src->getDimension();
const auto destDim = dest->getDimension();
if(srcDim.Width == 0 || srcDim.Height == 0 || destDim.Width == 0 || destDim.Height == 0)
return false;
if(src->getColorFormat() != dest->getColorFormat())
return false;
stbir_pixel_layout layout = STBIR_BGRA;
// Fast-paths (8-bit per channel only):
// - ECF_A8R8G8B8: Irrlicht stores as BGRA in memory on little-endian.
// - ECF_R8G8B8: common for JPEGs (3 channels).
switch(src->getColorFormat()) {
case irr::video::ECF_A8R8G8B8:
layout = STBIR_BGRA;
break;
case irr::video::ECF_R8G8B8:
layout = STBIR_RGB;
break;
default:
return false;
}
void* srcPtr = src->lock();
if(!srcPtr)
return false;
void* destPtr = dest->lock();
if(!destPtr) {
src->unlock();
return false;
}
const int srcStride = (int)src->getPitch();
const int destStride = (int)dest->getPitch();
thread_local StbSamplerCache cache;
cache.reset_if_needed((int)srcDim.Width, (int)srcDim.Height, (int)destDim.Width, (int)destDim.Height, layout);
if(!cache.samplers_built) {
stbir_resize_init(&cache.resize,
srcPtr, (int)srcDim.Width, (int)srcDim.Height, srcStride,
destPtr, (int)destDim.Width, (int)destDim.Height, destStride,
layout, STBIR_TYPE_UINT8);
stbir_set_edgemodes(&cache.resize, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP);
// Use box filters to reduce aliasing when downscaling.
stbir_set_filters(&cache.resize, STBIR_FILTER_BOX, STBIR_FILTER_BOX);
cache.samplers_built = (stbir_build_samplers(&cache.resize) != 0);
if(!cache.samplers_built) {
dest->unlock();
src->unlock();
return false;
}
} else {
// Reuse samplers but update buffer pointers for the current images
stbir_set_buffer_ptrs(&cache.resize, srcPtr, srcStride, destPtr, destStride);
}
const int ok = stbir_resize_extended(&cache.resize);
dest->unlock();
src->unlock();
return ok != 0;
}
/**
* Scale image using nearest neighbor anti-aliasing.
* Function by Warr1024, from https://github.com/minetest/minetest/issues/2419, modified.
*/
void ImageResizer::imageScaleNNAA(irr::video::IImage* src, irr::video::IImage* dest, bool use_threading) {
const auto& srcDim = src->getDimension();
const auto& destDim = dest->getDimension();
if (destDim.Width == 0 || destDim.Height == 0)
return;
// Cache scale ratios.
const double rx = (double)srcDim.Width / destDim.Width;
const double ry = (double)srcDim.Height / destDim.Height;
#pragma omp parallel if(use_threading)
{
// Walk each destination image pixel.
#pragma omp for schedule(dynamic)
for(irr::s32 dy = 0; dy < (irr::s32)destDim.Height; dy++) {
for(irr::s32 dx = 0; dx < (irr::s32)destDim.Width; dx++) {
// Calculate floating-point source rectangle bounds.
double minsx = dx * rx;
double maxsx = minsx + rx;
double minsy = dy * ry;
double maxsy = minsy + ry;
irr::u32 sx_begin = (irr::u32)std::floor(minsx);
irr::u32 sx_end = (irr::u32)std::ceil(maxsx);
if (sx_end > srcDim.Width)
sx_end = srcDim.Width;
irr::u32 sy_begin = (irr::u32)std::floor(minsy);
irr::u32 sy_end = (irr::u32)std::ceil(maxsy);
if (sy_end > srcDim.Height)
sy_end = srcDim.Height;
// Total area, and integral of r, g, b values over that area,
// initialized to zero, to be summed up in next loops.
double area = 0, ra = 0, ga = 0, ba = 0, aa = 0;
irr::video::SColor pxl, npxl;
// Loop over the integral pixel positions described by those bounds.
for(irr::u32 sy = sy_begin; sy < sy_end; sy++) {
for(irr::u32 sx = sx_begin; sx < sx_end; sx++) {
// Calculate width, height, then area of dest pixel
// that's covered by this source pixel.
double pw = 1;
if(minsx > sx)
pw += sx - minsx;
if(maxsx < (sx + 1))
pw += maxsx - sx - 1;
double ph = 1;
if(minsy > sy)
ph += sy - minsy;
if(maxsy < (sy + 1))
ph += maxsy - sy - 1;
double pa = pw * ph;
// Get source pixel and add it to totals, weighted
// by covered area and alpha.
pxl = src->getPixel(sx, sy);
area += pa;
ra += pa * pxl.getRed();
ga += pa * pxl.getGreen();
ba += pa * pxl.getBlue();
aa += pa * pxl.getAlpha();
}
}
// Set the destination image pixel to the average color.
if(area > 0) {
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 {
npxl.set(0);
}
dest->setPixel(dx, dy, npxl);
}
}
} // end of parallel region
}
void ImageResizer::resize(irr::video::IImage* src, irr::video::IImage* dest, bool use_threading) {
if(imageScaleSTB(src, dest))
return;
imageScaleNNAA(src, dest, use_threading);
}
} // namespace ygo
#ifndef IMAGE_RESIZER_H
#define IMAGE_RESIZER_H
#include <irrlicht.h>
namespace ygo {
class ImageResizer {
private:
bool imageScaleSTB(irr::video::IImage* src, irr::video::IImage* dest);
void imageScaleNNAA(irr::video::IImage* src, irr::video::IImage* dest, bool use_threading);
public:
void resize(irr::video::IImage* src, irr::video::IImage* dest, bool use_threading);
};
extern ImageResizer imageResizer;
} // namespace ygo
#endif // IMAGE_RESIZER_H
...@@ -15,17 +15,7 @@ namespace ygo { ...@@ -15,17 +15,7 @@ namespace ygo {
void UpdateDeck() { void UpdateDeck() {
BufferIO::CopyWideString(mainGame->cbCategorySelect->getText(), mainGame->gameConf.lastcategory); BufferIO::CopyWideString(mainGame->cbCategorySelect->getText(), mainGame->gameConf.lastcategory);
BufferIO::CopyWideString(mainGame->cbDeckSelect->getText(), mainGame->gameConf.lastdeck); BufferIO::CopyWideString(mainGame->cbDeckSelect->getText(), mainGame->gameConf.lastdeck);
unsigned char deckbuf[1024]{}; DuelClient::SendUpdateDeck(deckManager.current_deck);
auto pdeck = deckbuf;
BufferIO::Write<int32_t>(pdeck, static_cast<int32_t>(deckManager.current_deck.main.size() + deckManager.current_deck.extra.size()));
BufferIO::Write<int32_t>(pdeck, static_cast<int32_t>(deckManager.current_deck.side.size()));
for(size_t i = 0; i < deckManager.current_deck.main.size(); ++i)
BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.main[i]->first);
for(size_t i = 0; i < deckManager.current_deck.extra.size(); ++i)
BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.extra[i]->first);
for(size_t i = 0; i < deckManager.current_deck.side.size(); ++i)
BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.side[i]->first);
DuelClient::SendBufferToServer(CTOS_UPDATE_DECK, deckbuf, pdeck - deckbuf);
} }
bool MenuHandler::OnEvent(const irr::SEvent& event) { bool MenuHandler::OnEvent(const irr::SEvent& event) {
if(mainGame->dField.OnCommonEvent(event)) if(mainGame->dField.OnCommonEvent(event))
......
...@@ -8,8 +8,10 @@ ...@@ -8,8 +8,10 @@
#ifndef _WIN32 #ifndef _WIN32
#include <dirent.h> #include <dirent.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <string>
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
...@@ -182,7 +184,7 @@ public: ...@@ -182,7 +184,7 @@ public:
bool success = true; bool success = true;
TraversalDir(dir, [dir, &success](const char *name, bool isdir) { TraversalDir(dir, [dir, &success](const char *name, bool isdir) {
char full_path[1024]; char full_path[1024];
int len = mysnprintf(full_path, "%s/%s", dir, name); int len = std::snprintf(full_path, sizeof(full_path), "%s/%s", dir, name);
if (len < 0 || len >= (int)(sizeof full_path)) { if (len < 0 || len >= (int)(sizeof full_path)) {
success = false; success = false;
return; return;
...@@ -228,7 +230,7 @@ public: ...@@ -228,7 +230,7 @@ public:
while((dirp = readdir(dir)) != nullptr) { while((dirp = readdir(dir)) != nullptr) {
file_unit funit; file_unit funit;
char fname[1024]; char fname[1024];
int len = mysnprintf(fname, "%s/%s", path, dirp->d_name); int len = std::snprintf(fname, sizeof(fname), "%s/%s", path, dirp->d_name);
if (len < 0 || len >= (int)(sizeof fname)) if (len < 0 || len >= (int)(sizeof fname))
continue; continue;
stat(fname, &fileStat); stat(fname, &fileStat);
......
...@@ -172,14 +172,14 @@ constexpr int LEN_CHAT_PLAYER = 1; ...@@ -172,14 +172,14 @@ constexpr int LEN_CHAT_PLAYER = 1;
constexpr int LEN_CHAT_MSG = 256; constexpr int LEN_CHAT_MSG = 256;
constexpr int SIZE_STOC_CHAT = (LEN_CHAT_PLAYER + LEN_CHAT_MSG) * sizeof(uint16_t); constexpr int SIZE_STOC_CHAT = (LEN_CHAT_PLAYER + LEN_CHAT_MSG) * sizeof(uint16_t);
#pragma pack(push, 1)
struct STOC_HS_PlayerEnter { struct STOC_HS_PlayerEnter {
uint16_t name[20]{}; uint16_t name[20]{};
uint8_t pos{}; uint8_t pos{};
// byte padding[1]
}; };
#pragma pack(pop)
check_trivially_copyable(STOC_HS_PlayerEnter); check_trivially_copyable(STOC_HS_PlayerEnter);
//static_assert(sizeof(STOC_HS_PlayerEnter) == 42, "size mismatch: STOC_HS_PlayerEnter"); static_assert(sizeof(STOC_HS_PlayerEnter) == 41, "size mismatch: STOC_HS_PlayerEnter");
constexpr int STOC_HS_PlayerEnter_size = 41; //workwround
struct STOC_HS_PlayerChange { struct STOC_HS_PlayerChange {
//pos<<4 | state //pos<<4 | state
......
...@@ -88,143 +88,142 @@ void SoundManager::PlaySoundEffect(int sound) { ...@@ -88,143 +88,142 @@ void SoundManager::PlaySoundEffect(int sound) {
#ifdef YGOPRO_USE_AUDIO #ifdef YGOPRO_USE_AUDIO
if(!mainGame->chkEnableSound->isChecked()) if(!mainGame->chkEnableSound->isChecked())
return; return;
char soundName[32]; std::string soundName;
switch(sound) { switch(sound) {
case SOUND_SUMMON: { case SOUND_SUMMON: {
strcpy(soundName, "summon"); soundName = "summon";
break; break;
} }
case SOUND_SPECIAL_SUMMON: { case SOUND_SPECIAL_SUMMON: {
strcpy(soundName, "specialsummon"); soundName = "specialsummon";
break; break;
} }
case SOUND_ACTIVATE: { case SOUND_ACTIVATE: {
strcpy(soundName, "activate"); soundName = "activate";
break; break;
} }
case SOUND_SET: { case SOUND_SET: {
strcpy(soundName, "set"); soundName = "set";
break; break;
} }
case SOUND_FILP: { case SOUND_FLIP: {
strcpy(soundName, "flip"); soundName = "flip";
break; break;
} }
case SOUND_REVEAL: { case SOUND_REVEAL: {
strcpy(soundName, "reveal"); soundName = "reveal";
break; break;
} }
case SOUND_EQUIP: { case SOUND_EQUIP: {
strcpy(soundName, "equip"); soundName = "equip";
break; break;
} }
case SOUND_DESTROYED: { case SOUND_DESTROYED: {
strcpy(soundName, "destroyed"); soundName = "destroyed";
break; break;
} }
case SOUND_BANISHED: { case SOUND_BANISHED: {
strcpy(soundName, "banished"); soundName = "banished";
break; break;
} }
case SOUND_TOKEN: { case SOUND_TOKEN: {
strcpy(soundName, "token"); soundName = "token";
break; break;
} }
case SOUND_NEGATE: { case SOUND_NEGATE: {
strcpy(soundName, "negate"); soundName = "negate";
break; break;
} }
case SOUND_ATTACK: { case SOUND_ATTACK: {
strcpy(soundName, "attack"); soundName = "attack";
break; break;
} }
case SOUND_DIRECT_ATTACK: { case SOUND_DIRECT_ATTACK: {
strcpy(soundName, "directattack"); soundName = "directattack";
break; break;
} }
case SOUND_DRAW: { case SOUND_DRAW: {
strcpy(soundName, "draw"); soundName = "draw";
break; break;
} }
case SOUND_SHUFFLE: { case SOUND_SHUFFLE: {
strcpy(soundName, "shuffle"); soundName = "shuffle";
break; break;
} }
case SOUND_DAMAGE: { case SOUND_DAMAGE: {
strcpy(soundName, "damage"); soundName = "damage";
break; break;
} }
case SOUND_RECOVER: { case SOUND_RECOVER: {
strcpy(soundName, "gainlp"); soundName = "gainlp";
break; break;
} }
case SOUND_COUNTER_ADD: { case SOUND_COUNTER_ADD: {
strcpy(soundName, "addcounter"); soundName = "addcounter";
break; break;
} }
case SOUND_COUNTER_REMOVE: { case SOUND_COUNTER_REMOVE: {
strcpy(soundName, "removecounter"); soundName = "removecounter";
break; break;
} }
case SOUND_COIN: { case SOUND_COIN: {
strcpy(soundName, "coinflip"); soundName = "coinflip";
break; break;
} }
case SOUND_DICE: { case SOUND_DICE: {
strcpy(soundName, "diceroll"); soundName = "diceroll";
break; break;
} }
case SOUND_NEXT_TURN: { case SOUND_NEXT_TURN: {
strcpy(soundName, "nextturn"); soundName = "nextturn";
break; break;
} }
case SOUND_PHASE: { case SOUND_PHASE: {
strcpy(soundName, "phase"); soundName = "phase";
break; break;
} }
case SOUND_MENU: { case SOUND_MENU: {
strcpy(soundName, "menu"); soundName = "menu";
break; break;
} }
case SOUND_BUTTON: { case SOUND_BUTTON: {
strcpy(soundName, "button"); soundName = "button";
break; break;
} }
case SOUND_INFO: { case SOUND_INFO: {
strcpy(soundName, "info"); soundName = "info";
break; break;
} }
case SOUND_QUESTION: { case SOUND_QUESTION: {
strcpy(soundName, "question"); soundName = "question";
break; break;
} }
case SOUND_CARD_PICK: { case SOUND_CARD_PICK: {
strcpy(soundName, "cardpick"); soundName = "cardpick";
break; break;
} }
case SOUND_CARD_DROP: { case SOUND_CARD_DROP: {
strcpy(soundName, "carddrop"); soundName = "carddrop";
break; break;
} }
case SOUND_PLAYER_ENTER: { case SOUND_PLAYER_ENTER: {
strcpy(soundName, "playerenter"); soundName = "playerenter";
break; break;
} }
case SOUND_CHAT: { case SOUND_CHAT: {
strcpy(soundName, "chatmessage"); soundName = "chatmessage";
break; break;
} }
default: default:
break; return;
} }
char soundPath[40]; std::string soundPath = "./sound/" + soundName + ".wav";
mysnprintf(soundPath, "./sound/%s.wav", soundName);
SetSoundVolume(mainGame->gameConf.sound_volume); SetSoundVolume(mainGame->gameConf.sound_volume);
#ifdef YGOPRO_USE_MINIAUDIO #ifdef YGOPRO_USE_MINIAUDIO
ma_engine_play_sound(&engineSound, soundPath, nullptr); ma_engine_play_sound(&engineSound, soundPath.c_str(), nullptr);
#endif #endif
#ifdef YGOPRO_USE_IRRKLANG #ifdef YGOPRO_USE_IRRKLANG
engineSound->play2D(soundPath); engineSound->play2D(soundPath.c_str());
#endif #endif
#endif // YGOPRO_USE_AUDIO #endif // YGOPRO_USE_AUDIO
} }
......
...@@ -54,7 +54,7 @@ extern SoundManager soundManager; ...@@ -54,7 +54,7 @@ extern SoundManager soundManager;
#define SOUND_SPECIAL_SUMMON 102 #define SOUND_SPECIAL_SUMMON 102
#define SOUND_ACTIVATE 103 #define SOUND_ACTIVATE 103
#define SOUND_SET 104 #define SOUND_SET 104
#define SOUND_FILP 105 #define SOUND_FLIP 105
#define SOUND_REVEAL 106 #define SOUND_REVEAL 106
#define SOUND_EQUIP 107 #define SOUND_EQUIP 107
#define SOUND_DESTROYED 108 #define SOUND_DESTROYED 108
......
This diff is collapsed.
This diff is collapsed.
...@@ -671,6 +671,7 @@ ...@@ -671,6 +671,7 @@
!counter 0x70 盘子指示物 !counter 0x70 盘子指示物
!counter 0x71 纠罪指示物 !counter 0x71 纠罪指示物
!counter 0x1072 少女指示物 !counter 0x1072 少女指示物
!counter 0x73 T指示物
#setnames, using tab for comment #setnames, using tab for comment
!setname 0x1 正义盟军 AOJ !setname 0x1 正义盟军 AOJ
!setname 0x2 次世代 ジェネクス !setname 0x2 次世代 ジェネクス
...@@ -832,7 +833,7 @@ ...@@ -832,7 +833,7 @@
!setname 0x106e 魔导书 魔導書 !setname 0x106e 魔导书 魔導書
!setname 0x6f 英豪 ヒロイック !setname 0x6f 英豪 ヒロイック
!setname 0x106f 英豪挑战者 HC !setname 0x106f 英豪挑战者 HC
#setname 0x206f 英豪冠军 H-C !setname 0x206f 英豪冠军 HC
!setname 0x70 先史遗产 先史遺産 !setname 0x70 先史遗产 先史遺産
!setname 0x71 魔偶甜点 マドルチェ !setname 0x71 魔偶甜点 マドルチェ
!setname 0x72 齿轮齿轮 ギアギア !setname 0x72 齿轮齿轮 ギアギア
...@@ -1278,3 +1279,6 @@ ...@@ -1278,3 +1279,6 @@
!setname 0x1d8 耀圣 エルフェンノーツ !setname 0x1d8 耀圣 エルフェンノーツ
!setname 0x1d9 磁力 マグネット !setname 0x1d9 磁力 マグネット
!setname 0x1da 世界末日 エンド・オブ・ザ・ワールド !setname 0x1da 世界末日 エンド・オブ・ザ・ワールド
!setname 0x1db 妖精传姬 妖精伝姫
!setname 0x1dc 道化一座 道化の一座
!setname 0x1dd GMX
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