Commit 1cd16fb5 authored by mercury233's avatar mercury233

Merge branch 'fh' into patch-premake-freetype

parents c5ecca83 61812083
...@@ -144,7 +144,7 @@ jobs: ...@@ -144,7 +144,7 @@ jobs:
uses: mercury233/action-cache-download-file@v1.0.0 uses: mercury233/action-cache-download-file@v1.0.0
with: with:
url: https://github.com/xiph/opus/releases/download/v1.5.2/opus-1.5.2.tar.gz url: https://github.com/xiph/opus/releases/download/v1.5.2/opus-1.5.2.tar.gz
- name: Extract opus - name: Extract opus
if: matrix.audiolib == 'miniaudio' if: matrix.audiolib == 'miniaudio'
run: | run: |
...@@ -398,7 +398,7 @@ jobs: ...@@ -398,7 +398,7 @@ jobs:
uses: mercury233/action-cache-download-file@v1.0.0 uses: mercury233/action-cache-download-file@v1.0.0
with: with:
url: https://github.com/xiph/opus/releases/download/v1.5.2/opus-1.5.2.tar.gz url: https://github.com/xiph/opus/releases/download/v1.5.2/opus-1.5.2.tar.gz
- name: Extract opus - name: Extract opus
if: matrix.static-link == true if: matrix.static-link == true
run: | run: |
...@@ -625,7 +625,7 @@ jobs: ...@@ -625,7 +625,7 @@ jobs:
uses: mercury233/action-cache-download-file@v1.0.0 uses: mercury233/action-cache-download-file@v1.0.0
with: with:
url: https://github.com/xiph/opus/releases/download/v1.5.2/opus-1.5.2.tar.gz url: https://github.com/xiph/opus/releases/download/v1.5.2/opus-1.5.2.tar.gz
- name: Extract opus - name: Extract opus
if: matrix.static-link == true if: matrix.static-link == true
run: | run: |
...@@ -679,7 +679,7 @@ jobs: ...@@ -679,7 +679,7 @@ jobs:
--build-event \ --build-event \
--build-freetype \ --build-freetype \
--build-sqlite \ --build-sqlite \
--build-opus-vorbis --build-opus-vorbis
- name: Make - name: Make
run: | run: |
......
...@@ -2,31 +2,52 @@ ...@@ -2,31 +2,52 @@
#define BUFFERIO_H #define BUFFERIO_H
#include <cstdint> #include <cstdint>
#include <cstring>
#include <cwchar> #include <cwchar>
#include "../ocgcore/buffer.h"
class BufferIO { class BufferIO {
public: public:
static int ReadInt32(unsigned char*& p) { template<typename T>
return buffer_read<int32_t>(p); static T Read(unsigned char*& p) {
T ret{};
std::memcpy(&ret, p, sizeof(T));
p += sizeof(T);
return ret;
}
template<typename T>
static void Write(unsigned char*& p, T value) {
std::memcpy(p, &value, sizeof(T));
p += sizeof(T);
}
// for compatibility
[[deprecated]]
static int32_t ReadInt32(unsigned char*& p) {
return Read<int32_t>(p);
} }
[[deprecated]]
static short ReadInt16(unsigned char*& p) { static short ReadInt16(unsigned char*& p) {
return buffer_read<int16_t>(p); return Read<int16_t>(p);
} }
[[deprecated]]
static char ReadInt8(unsigned char*& p) { static char ReadInt8(unsigned char*& p) {
return buffer_read<char>(p); return Read<char>(p);
} }
[[deprecated]]
static unsigned char ReadUInt8(unsigned char*& p) { static unsigned char ReadUInt8(unsigned char*& p) {
return buffer_read<unsigned char>(p); return Read<unsigned char>(p);
} }
static void WriteInt32(unsigned char*& p, int val) { [[deprecated]]
buffer_write<int32_t>(p, val); static void WriteInt32(unsigned char*& p, int32_t val) {
Write<int32_t>(p, val);
} }
[[deprecated]]
static void WriteInt16(unsigned char*& p, short val) { static void WriteInt16(unsigned char*& p, short val) {
buffer_write<int16_t>(p, val); Write<int16_t>(p, val);
} }
[[deprecated]]
static void WriteInt8(unsigned char*& p, char val) { static void WriteInt8(unsigned char*& p, char val) {
buffer_write<char>(p, val); Write<char>(p, val);
} }
/** /**
* @brief Copy a C-style string to another C-style string. * @brief Copy a C-style string to another C-style string.
...@@ -61,64 +82,18 @@ public: ...@@ -61,64 +82,18 @@ public:
return CopyWStr(src, dst, N); return CopyWStr(src, dst, N);
} }
template<size_t N> template<size_t N>
static void CopyString(const char* src, char(&dst)[N]) { static void CopyString(const char* src, char(&dst)[N], size_t len = N - 1) {
std::strncpy(dst, src, N - 1); if(len >= N)
dst[N - 1] = 0; len = N - 1;
std::strncpy(dst, src, len);
dst[len] = 0;
} }
template<size_t N> template<size_t N>
static void CopyWideString(const wchar_t* src, wchar_t(&dst)[N]) { static void CopyWideString(const wchar_t* src, wchar_t(&dst)[N], size_t len = N - 1) {
std::wcsncpy(dst, src, N - 1); if(len >= N)
dst[N - 1] = 0; len = N - 1;
} std::wcsncpy(dst, src, len);
template<typename T> dst[len] = 0;
static bool CheckUTF8Byte(const T* str, int len) {
for (int i = 1; i < len; ++i) {
if ((str[i] & 0xc0U) != 0x80U)
return false;
}
return true;
}
static unsigned int ConvertUTF8(const char*& p) {
unsigned int cur = 0;
if ((p[0] & 0x80U) == 0) {
cur = p[0] & 0xffU;
p++;
}
else if ((p[0] & 0xe0U) == 0xc0U) {
if (!CheckUTF8Byte(p, 2)) {
p++;
return UINT32_MAX;
}
cur = ((p[0] & 0x1fU) << 6) | (p[1] & 0x3fU);
p += 2;
if(cur < 0x80U)
return UINT32_MAX;
}
else if ((p[0] & 0xf0U) == 0xe0U) {
if (!CheckUTF8Byte(p, 3)) {
p++;
return UINT32_MAX;
}
cur = ((p[0] & 0xfU) << 12) | ((p[1] & 0x3fU) << 6) | (p[2] & 0x3fU);
p += 3;
if (cur < 0x800U)
return UINT32_MAX;
}
else if ((p[0] & 0xf8U) == 0xf0U) {
if (!CheckUTF8Byte(p, 4)) {
p++;
return UINT32_MAX;
}
cur = ((p[0] & 0x7U) << 18) | ((p[1] & 0x3fU) << 12) | ((p[2] & 0x3fU) << 6) | (p[3] & 0x3fU);
p += 4;
if (cur < 0x10000U)
return UINT32_MAX;
}
else {
p++;
return UINT32_MAX;
}
return cur;
} }
static bool IsHighSurrogate(unsigned int c) { static bool IsHighSurrogate(unsigned int c) {
return (c >= 0xd800U && c <= 0xdbffU); return (c >= 0xd800U && c <= 0xdbffU);
...@@ -137,111 +112,31 @@ public: ...@@ -137,111 +112,31 @@ public:
} }
// UTF-16/UTF-32 to UTF-8 // UTF-16/UTF-32 to UTF-8
// return: string length // return: string length
static int EncodeUTF8String(const wchar_t* wsrc, char* str, int size) { static int EncodeUTF8String(const wchar_t* wsrc, char* str, size_t len) {
auto pw = wsrc; if (len == 0) {
auto pstr = str; str[0] = 0;
while (*pw != 0) { return 0;
unsigned cur = 0;
int codepoint_size = 0;
if (sizeof(wchar_t) == 2) {
if (IsHighSurrogate(pw[0])) {
if (pw[1] == 0)
break;
if (IsLowSurrogate(pw[1])) {
cur = ((pw[0] & 0x3ffU) << 10) | (pw[1] & 0x3ffU);
cur += 0x10000;
pw += 2;
}
else {
pw++;
continue;
}
}
else if (IsLowSurrogate(pw[0])) {
pw++;
continue;
}
else {
cur = *pw;
pw++;
}
}
else {
cur = *pw;
pw++;
}
if (!IsUnicodeChar(cur))
continue;
if (cur < 0x80U)
codepoint_size = 1;
else if (cur < 0x800U)
codepoint_size = 2;
else if (cur < 0x10000U)
codepoint_size = 3;
else
codepoint_size = 4;
if ((int)(pstr - str) + codepoint_size > size - 1)
break;
switch (codepoint_size) {
case 1:
*pstr = (char)cur;
break;
case 2:
pstr[0] = ((cur >> 6) & 0x1f) | 0xc0;
pstr[1] = (cur & 0x3f) | 0x80;
break;
case 3:
pstr[0] = ((cur >> 12) & 0xf) | 0xe0;
pstr[1] = ((cur >> 6) & 0x3f) | 0x80;
pstr[2] = (cur & 0x3f) | 0x80;
break;
case 4:
pstr[0] = ((cur >> 18) & 0x7) | 0xf0;
pstr[1] = ((cur >> 12) & 0x3f) | 0x80;
pstr[2] = ((cur >> 6) & 0x3f) | 0x80;
pstr[3] = (cur & 0x3f) | 0x80;
break;
default:
break;
}
pstr += codepoint_size;
} }
*pstr = 0; std::mbstate_t state{};
return (int)(pstr - str); size_t result_len = std::wcsrtombs(str, &wsrc, len - 1, &state);
if (result_len == static_cast<size_t>(-1))
result_len = 0;
str[result_len] = 0;
return static_cast<int>(result_len);
} }
// UTF-8 to UTF-16/UTF-32 // UTF-8 to UTF-16/UTF-32
// return: string length // return: string length
static int DecodeUTF8String(const char* src, wchar_t* wstr, int size) { static int DecodeUTF8String(const char* src, wchar_t* wstr, size_t len) {
const char* p = src; if (len == 0) {
wchar_t* wp = wstr; wstr[0] = 0;
while(*p != 0) { return 0;
unsigned int cur = ConvertUTF8(p);
int codepoint_size = 0;
if (!IsUnicodeChar(cur))
continue;
if (cur >= 0x10000) {
if (sizeof(wchar_t) == 2)
codepoint_size = 2;
else
codepoint_size = 1;
}
else
codepoint_size = 1;
if ((int)(wp - wstr) + codepoint_size > size - 1)
break;
if (codepoint_size == 1) {
wp[0] = cur;
wp++;
}
else {
cur -= 0x10000U;
wp[0] = (cur >> 10) | 0xd800;
wp[1] = (cur & 0x3ff) | 0xdc00;
wp += 2;
}
} }
*wp = 0; std::mbstate_t state{};
return wp - wstr; size_t result_len = std::mbsrtowcs(wstr, &src, len - 1, &state);
if (result_len == static_cast<size_t>(-1))
result_len = 0;
wstr[result_len] = 0;
return static_cast<int>(result_len);
} }
template<size_t N> template<size_t N>
static int EncodeUTF8(const wchar_t* src, char(&dst)[N]) { static int EncodeUTF8(const wchar_t* src, char(&dst)[N]) {
...@@ -267,7 +162,6 @@ public: ...@@ -267,7 +162,6 @@ public:
} }
else else
return 0; return 0;
} }
}; };
......
...@@ -39,13 +39,13 @@ void ClientCard::SetCode(unsigned int x) { ...@@ -39,13 +39,13 @@ void ClientCard::SetCode(unsigned int x) {
code = x; code = x;
} }
void ClientCard::UpdateInfo(unsigned char* buf) { void ClientCard::UpdateInfo(unsigned char* buf) {
int flag = BufferIO::ReadInt32(buf); int flag = BufferIO::Read<int32_t>(buf);
if (flag == 0) { if (flag == 0) {
ClearData(); ClearData();
return; return;
} }
if(flag & QUERY_CODE) { if(flag & QUERY_CODE) {
int pdata = BufferIO::ReadInt32(buf); int pdata = BufferIO::Read<int32_t>(buf);
if (!pdata) if (!pdata)
ClearData(); ClearData();
if((location == LOCATION_HAND) && ((unsigned int)pdata != code)) { if((location == LOCATION_HAND) && ((unsigned int)pdata != code)) {
...@@ -55,7 +55,7 @@ void ClientCard::UpdateInfo(unsigned char* buf) { ...@@ -55,7 +55,7 @@ void ClientCard::UpdateInfo(unsigned char* buf) {
code = pdata; code = pdata;
} }
if(flag & QUERY_POSITION) { if(flag & QUERY_POSITION) {
int pdata = (BufferIO::ReadInt32(buf) >> 24) & 0xff; int pdata = (BufferIO::Read<int32_t>(buf) >> 24) & 0xff;
if((location & (LOCATION_EXTRA | LOCATION_REMOVED)) && pdata != position) { if((location & (LOCATION_EXTRA | LOCATION_REMOVED)) && pdata != position) {
position = pdata; position = pdata;
mainGame->dField.MoveCard(this, 1); mainGame->dField.MoveCard(this, 1);
...@@ -63,29 +63,29 @@ void ClientCard::UpdateInfo(unsigned char* buf) { ...@@ -63,29 +63,29 @@ void ClientCard::UpdateInfo(unsigned char* buf) {
position = pdata; position = pdata;
} }
if(flag & QUERY_ALIAS) if(flag & QUERY_ALIAS)
alias = BufferIO::ReadInt32(buf); alias = BufferIO::Read<int32_t>(buf);
if(flag & QUERY_TYPE) if(flag & QUERY_TYPE)
type = BufferIO::ReadInt32(buf); type = BufferIO::Read<int32_t>(buf);
if(flag & QUERY_LEVEL) { if(flag & QUERY_LEVEL) {
int pdata = BufferIO::ReadInt32(buf); int pdata = BufferIO::Read<int32_t>(buf);
if(level != (unsigned int)pdata) { if(level != (unsigned int)pdata) {
level = pdata; level = pdata;
myswprintf(lvstring, L"L%d", level); myswprintf(lvstring, L"L%d", level);
} }
} }
if(flag & QUERY_RANK) { if(flag & QUERY_RANK) {
int pdata = BufferIO::ReadInt32(buf); int pdata = BufferIO::Read<int32_t>(buf);
if(pdata && rank != (unsigned int)pdata) { if(pdata && rank != (unsigned int)pdata) {
rank = pdata; rank = pdata;
myswprintf(lvstring, L"R%d", rank); myswprintf(lvstring, L"R%d", rank);
} }
} }
if(flag & QUERY_ATTRIBUTE) if(flag & QUERY_ATTRIBUTE)
attribute = BufferIO::ReadInt32(buf); attribute = BufferIO::Read<int32_t>(buf);
if(flag & QUERY_RACE) if(flag & QUERY_RACE)
race = BufferIO::ReadInt32(buf); race = BufferIO::Read<int32_t>(buf);
if(flag & QUERY_ATTACK) { if(flag & QUERY_ATTACK) {
attack = BufferIO::ReadInt32(buf); attack = BufferIO::Read<int32_t>(buf);
if(attack < 0) { if(attack < 0) {
atkstring[0] = '?'; atkstring[0] = '?';
atkstring[1] = 0; atkstring[1] = 0;
...@@ -93,7 +93,7 @@ void ClientCard::UpdateInfo(unsigned char* buf) { ...@@ -93,7 +93,7 @@ void ClientCard::UpdateInfo(unsigned char* buf) {
myswprintf(atkstring, L"%d", attack); myswprintf(atkstring, L"%d", attack);
} }
if(flag & QUERY_DEFENSE) { if(flag & QUERY_DEFENSE) {
defense = BufferIO::ReadInt32(buf); defense = BufferIO::Read<int32_t>(buf);
if(type & TYPE_LINK) { if(type & TYPE_LINK) {
defstring[0] = '-'; defstring[0] = '-';
defstring[1] = 0; defstring[1] = 0;
...@@ -104,18 +104,18 @@ void ClientCard::UpdateInfo(unsigned char* buf) { ...@@ -104,18 +104,18 @@ void ClientCard::UpdateInfo(unsigned char* buf) {
myswprintf(defstring, L"%d", defense); myswprintf(defstring, L"%d", defense);
} }
if(flag & QUERY_BASE_ATTACK) if(flag & QUERY_BASE_ATTACK)
base_attack = BufferIO::ReadInt32(buf); base_attack = BufferIO::Read<int32_t>(buf);
if(flag & QUERY_BASE_DEFENSE) if(flag & QUERY_BASE_DEFENSE)
base_defense = BufferIO::ReadInt32(buf); base_defense = BufferIO::Read<int32_t>(buf);
if(flag & QUERY_REASON) if(flag & QUERY_REASON)
reason = BufferIO::ReadInt32(buf); reason = BufferIO::Read<int32_t>(buf);
if(flag & QUERY_REASON_CARD) if(flag & QUERY_REASON_CARD)
buf += 4; buf += 4;
if(flag & QUERY_EQUIP_CARD) { if(flag & QUERY_EQUIP_CARD) {
int c = BufferIO::ReadUInt8(buf); int c = BufferIO::Read<uint8_t>(buf);
unsigned int l = BufferIO::ReadUInt8(buf); unsigned int l = BufferIO::Read<uint8_t>(buf);
int s = BufferIO::ReadUInt8(buf); int s = BufferIO::Read<uint8_t>(buf);
BufferIO::ReadUInt8(buf); BufferIO::Read<uint8_t>(buf);
ClientCard* ecard = mainGame->dField.GetCard(mainGame->LocalPlayer(c), l, s); ClientCard* ecard = mainGame->dField.GetCard(mainGame->LocalPlayer(c), l, s);
if (ecard) { if (ecard) {
equipTarget = ecard; equipTarget = ecard;
...@@ -123,12 +123,12 @@ void ClientCard::UpdateInfo(unsigned char* buf) { ...@@ -123,12 +123,12 @@ void ClientCard::UpdateInfo(unsigned char* buf) {
} }
} }
if(flag & QUERY_TARGET_CARD) { if(flag & QUERY_TARGET_CARD) {
int count = BufferIO::ReadInt32(buf); int count = BufferIO::Read<int32_t>(buf);
for(int i = 0; i < count; ++i) { for(int i = 0; i < count; ++i) {
int c = BufferIO::ReadUInt8(buf); int c = BufferIO::Read<uint8_t>(buf);
unsigned int l = BufferIO::ReadUInt8(buf); unsigned int l = BufferIO::Read<uint8_t>(buf);
int s = BufferIO::ReadUInt8(buf); int s = BufferIO::Read<uint8_t>(buf);
BufferIO::ReadUInt8(buf); BufferIO::Read<uint8_t>(buf);
ClientCard* tcard = mainGame->dField.GetCard(mainGame->LocalPlayer(c), l, s); ClientCard* tcard = mainGame->dField.GetCard(mainGame->LocalPlayer(c), l, s);
if (tcard) { if (tcard) {
cardTarget.insert(tcard); cardTarget.insert(tcard);
...@@ -137,38 +137,38 @@ void ClientCard::UpdateInfo(unsigned char* buf) { ...@@ -137,38 +137,38 @@ void ClientCard::UpdateInfo(unsigned char* buf) {
} }
} }
if(flag & QUERY_OVERLAY_CARD) { if(flag & QUERY_OVERLAY_CARD) {
int count = BufferIO::ReadInt32(buf); int count = BufferIO::Read<int32_t>(buf);
for(int i = 0; i < count; ++i) { for(int i = 0; i < count; ++i) {
overlayed[i]->SetCode(BufferIO::ReadInt32(buf)); overlayed[i]->SetCode(BufferIO::Read<int32_t>(buf));
} }
} }
if(flag & QUERY_COUNTERS) { if(flag & QUERY_COUNTERS) {
int count = BufferIO::ReadInt32(buf); int count = BufferIO::Read<int32_t>(buf);
for(int i = 0; i < count; ++i) { for(int i = 0; i < count; ++i) {
int ctype = BufferIO::ReadInt16(buf); int ctype = BufferIO::Read<uint16_t>(buf);
int ccount = BufferIO::ReadInt16(buf); int ccount = BufferIO::Read<uint16_t>(buf);
counters[ctype] = ccount; counters[ctype] = ccount;
} }
} }
if(flag & QUERY_OWNER) if(flag & QUERY_OWNER)
owner = BufferIO::ReadInt32(buf); owner = BufferIO::Read<int32_t>(buf);
if(flag & QUERY_STATUS) if(flag & QUERY_STATUS)
status = BufferIO::ReadInt32(buf); status = BufferIO::Read<int32_t>(buf);
if(flag & QUERY_LSCALE) { if(flag & QUERY_LSCALE) {
lscale = BufferIO::ReadInt32(buf); lscale = BufferIO::Read<int32_t>(buf);
myswprintf(lscstring, L"%d", lscale); myswprintf(lscstring, L"%d", lscale);
} }
if(flag & QUERY_RSCALE) { if(flag & QUERY_RSCALE) {
rscale = BufferIO::ReadInt32(buf); rscale = BufferIO::Read<int32_t>(buf);
myswprintf(rscstring, L"%d", rscale); myswprintf(rscstring, L"%d", rscale);
} }
if(flag & QUERY_LINK) { if(flag & QUERY_LINK) {
int pdata = BufferIO::ReadInt32(buf); int pdata = BufferIO::Read<int32_t>(buf);
if (link != (unsigned int)pdata) { if (link != (unsigned int)pdata) {
link = pdata; link = pdata;
} }
myswprintf(linkstring, L"L\x2012%d", link); myswprintf(linkstring, L"L\x2012%d", link);
pdata = BufferIO::ReadInt32(buf); pdata = BufferIO::Read<int32_t>(buf);
if (link_marker != (unsigned int)pdata) { if (link_marker != (unsigned int)pdata) {
link_marker = pdata; link_marker = pdata;
} }
......
...@@ -222,12 +222,12 @@ void ClientField::AddCard(ClientCard* pcard, int controler, int location, int se ...@@ -222,12 +222,12 @@ void ClientField::AddCard(ClientCard* pcard, int controler, int location, int se
} }
case LOCATION_GRAVE: { case LOCATION_GRAVE: {
grave[controler].push_back(pcard); grave[controler].push_back(pcard);
ResetSequence(grave[controler], false); pcard->sequence = (unsigned char)(grave[controler].size() - 1);
break; break;
} }
case LOCATION_REMOVED: { case LOCATION_REMOVED: {
remove[controler].push_back(pcard); remove[controler].push_back(pcard);
ResetSequence(remove[controler], false); pcard->sequence = (unsigned char)(remove[controler].size() - 1);
break; break;
} }
case LOCATION_EXTRA: { case LOCATION_EXTRA: {
...@@ -249,8 +249,13 @@ ClientCard* ClientField::RemoveCard(int controler, int location, int sequence) { ...@@ -249,8 +249,13 @@ ClientCard* ClientField::RemoveCard(int controler, int location, int sequence) {
switch (location) { switch (location) {
case LOCATION_DECK: { case LOCATION_DECK: {
pcard = deck[controler][sequence]; pcard = deck[controler][sequence];
deck[controler].erase(deck[controler].begin() + sequence); for (size_t i = sequence; i < deck[controler].size() - 1; ++i) {
ResetSequence(deck[controler], true); deck[controler][i] = deck[controler][i + 1];
deck[controler][i]->sequence--;
deck[controler][i]->curPos -= irr::core::vector3df(0, 0, 0.01f);
deck[controler][i]->mTransform.setTranslation(deck[controler][i]->curPos);
}
deck[controler].erase(deck[controler].end() - 1);
break; break;
} }
case LOCATION_HAND: { case LOCATION_HAND: {
...@@ -271,20 +276,35 @@ ClientCard* ClientField::RemoveCard(int controler, int location, int sequence) { ...@@ -271,20 +276,35 @@ ClientCard* ClientField::RemoveCard(int controler, int location, int sequence) {
} }
case LOCATION_GRAVE: { case LOCATION_GRAVE: {
pcard = grave[controler][sequence]; pcard = grave[controler][sequence];
grave[controler].erase(grave[controler].begin() + sequence); for (size_t i = sequence; i < grave[controler].size() - 1; ++i) {
ResetSequence(grave[controler], true); grave[controler][i] = grave[controler][i + 1];
grave[controler][i]->sequence--;
grave[controler][i]->curPos -= irr::core::vector3df(0, 0, 0.01f);
grave[controler][i]->mTransform.setTranslation(grave[controler][i]->curPos);
}
grave[controler].erase(grave[controler].end() - 1);
break; break;
} }
case LOCATION_REMOVED: { case LOCATION_REMOVED: {
pcard = remove[controler][sequence]; pcard = remove[controler][sequence];
remove[controler].erase(remove[controler].begin() + sequence); for (size_t i = sequence; i < remove[controler].size() - 1; ++i) {
ResetSequence(remove[controler], true); remove[controler][i] = remove[controler][i + 1];
remove[controler][i]->sequence--;
remove[controler][i]->curPos -= irr::core::vector3df(0, 0, 0.01f);
remove[controler][i]->mTransform.setTranslation(remove[controler][i]->curPos);
}
remove[controler].erase(remove[controler].end() - 1);
break; break;
} }
case LOCATION_EXTRA: { case LOCATION_EXTRA: {
pcard = extra[controler][sequence]; pcard = extra[controler][sequence];
extra[controler].erase(extra[controler].begin() + sequence); for (size_t i = sequence; i < extra[controler].size() - 1; ++i) {
ResetSequence(extra[controler], true); extra[controler][i] = extra[controler][i + 1];
extra[controler][i]->sequence--;
extra[controler][i]->curPos -= irr::core::vector3df(0, 0, 0.01f);
extra[controler][i]->mTransform.setTranslation(extra[controler][i]->curPos);
}
extra[controler].erase(extra[controler].end() - 1);
if (pcard->position & POS_FACEUP) if (pcard->position & POS_FACEUP)
extra_p_count[controler]--; extra_p_count[controler]--;
break; break;
...@@ -297,7 +317,7 @@ ClientCard* ClientField::RemoveCard(int controler, int location, int sequence) { ...@@ -297,7 +317,7 @@ ClientCard* ClientField::RemoveCard(int controler, int location, int sequence) {
} }
void ClientField::UpdateCard(int controler, int location, int sequence, unsigned char* data) { void ClientField::UpdateCard(int controler, int location, int sequence, unsigned char* data) {
ClientCard* pcard = GetCard(controler, location, sequence); ClientCard* pcard = GetCard(controler, location, sequence);
int len = BufferIO::ReadInt32(data); int len = BufferIO::Read<int32_t>(data);
if (pcard && len > LEN_HEADER) if (pcard && len > LEN_HEADER)
pcard->UpdateInfo(data); pcard->UpdateInfo(data);
} }
...@@ -330,7 +350,7 @@ void ClientField::UpdateFieldCard(int controler, int location, unsigned char* da ...@@ -330,7 +350,7 @@ void ClientField::UpdateFieldCard(int controler, int location, unsigned char* da
return; return;
int len; int len;
for(auto cit = lst->begin(); cit != lst->end(); ++cit) { for(auto cit = lst->begin(); cit != lst->end(); ++cit) {
len = BufferIO::ReadInt32(data); len = BufferIO::Read<int32_t>(data);
if(len > LEN_HEADER) if(len > LEN_HEADER)
(*cit)->UpdateInfo(data); (*cit)->UpdateInfo(data);
data += len - 4; data += len - 4;
...@@ -1188,8 +1208,8 @@ bool ClientField::CheckSelectSum() { ...@@ -1188,8 +1208,8 @@ bool ClientField::CheckSelectSum() {
int mm = -1, mx = -1, max = 0, sumc = 0; int mm = -1, mx = -1, max = 0, sumc = 0;
bool ret = false; bool ret = false;
for (auto sc : selected_cards) { for (auto sc : selected_cards) {
int op1 = sc->opParam & 0xffff; int op1, op2;
int op2 = sc->opParam >> 16; get_sum_params(sc->opParam, op1, op2);
int opmin = (op2 > 0 && op1 > op2) ? op2 : op1; int opmin = (op2 > 0 && op1 > op2) ? op2 : op1;
int opmax = op2 > op1 ? op2 : op1; int opmax = op2 > op1 ? op2 : op1;
if (mm == -1 || opmin < mm) if (mm == -1 || opmin < mm)
...@@ -1204,8 +1224,8 @@ bool ClientField::CheckSelectSum() { ...@@ -1204,8 +1224,8 @@ bool ClientField::CheckSelectSum() {
if (select_sumval <= max && select_sumval > max - mx) if (select_sumval <= max && select_sumval > max - mx)
ret = true; ret = true;
for(auto sc : selable) { for(auto sc : selable) {
int op1 = sc->opParam & 0xffff; int op1, op2;
int op2 = sc->opParam >> 16; get_sum_params(sc->opParam, op1, op2);
int m = op1; int m = op1;
int sums = sumc; int sums = sumc;
sums += m; sums += m;
...@@ -1271,11 +1291,19 @@ bool ClientField::CheckSelectTribute() { ...@@ -1271,11 +1291,19 @@ bool ClientField::CheckSelectTribute() {
} }
return ret; return ret;
} }
void ClientField::get_sum_params(unsigned int opParam, int& op1, int& op2) {
op1 = opParam & 0xffff;
op2 = (opParam >> 16) & 0xffff;
if (op2 & 0x8000) {
op1 = opParam & 0x7fffffff;
op2 = 0;
}
}
bool ClientField::check_min(const std::set<ClientCard*>& left, std::set<ClientCard*>::const_iterator index, int min, int max) { bool ClientField::check_min(const std::set<ClientCard*>& left, std::set<ClientCard*>::const_iterator index, int min, int max) {
if (index == left.end()) if (index == left.end())
return false; return false;
int op1 = (*index)->opParam & 0xffff; int op1, op2;
int op2 = (*index)->opParam >> 16; get_sum_params((*index)->opParam, op1, op2);
int m = (op2 > 0 && op1 > op2) ? op2 : op1; int m = (op2 > 0 && op1 > op2) ? op2 : op1;
if (m >= min && m <= max) if (m >= min && m <= max)
return true; return true;
...@@ -1294,9 +1322,8 @@ bool ClientField::check_sel_sum_s(const std::set<ClientCard*>& left, int index, ...@@ -1294,9 +1322,8 @@ bool ClientField::check_sel_sum_s(const std::set<ClientCard*>& left, int index,
check_sel_sum_t(left, acc); check_sel_sum_t(left, acc);
return false; return false;
} }
int l = selected_cards[index]->opParam; int l1, l2;
int l1 = l & 0xffff; get_sum_params(selected_cards[index]->opParam, l1, l2);
int l2 = l >> 16;
bool res1 = false, res2 = false; bool res1 = false, res2 = false;
res1 = check_sel_sum_s(left, index + 1, acc - l1); res1 = check_sel_sum_s(left, index + 1, acc - l1);
if (l2 > 0) if (l2 > 0)
...@@ -1310,9 +1337,8 @@ void ClientField::check_sel_sum_t(const std::set<ClientCard*>& left, int acc) { ...@@ -1310,9 +1337,8 @@ void ClientField::check_sel_sum_t(const std::set<ClientCard*>& left, int acc) {
continue; continue;
std::set<ClientCard*> testlist(left); std::set<ClientCard*> testlist(left);
testlist.erase(*sit); testlist.erase(*sit);
int l = (*sit)->opParam; int l1, l2;
int l1 = l & 0xffff; get_sum_params((*sit)->opParam, l1, l2);
int l2 = l >> 16;
if (check_sum(testlist.begin(), testlist.end(), acc - l1, count) if (check_sum(testlist.begin(), testlist.end(), acc - l1, count)
|| (l2 > 0 && check_sum(testlist.begin(), testlist.end(), acc - l2, count))) { || (l2 > 0 && check_sum(testlist.begin(), testlist.end(), acc - l2, count))) {
selectsum_cards.insert(*sit); selectsum_cards.insert(*sit);
...@@ -1324,9 +1350,8 @@ bool ClientField::check_sum(std::set<ClientCard*>::const_iterator index, std::se ...@@ -1324,9 +1350,8 @@ bool ClientField::check_sum(std::set<ClientCard*>::const_iterator index, std::se
return count >= select_min && count <= select_max; return count >= select_min && count <= select_max;
if (acc < 0 || index == end) if (acc < 0 || index == end)
return false; return false;
int l = (*index)->opParam; int l1, l2;
int l1 = l & 0xffff; get_sum_params((*index)->opParam, l1, l2);
int l2 = l >> 16;
if ((l1 == acc || (l2 > 0 && l2 == acc)) && (count + 1 >= select_min) && (count + 1 <= select_max)) if ((l1 == acc || (l2 > 0 && l2 == acc)) && (count + 1 >= select_min) && (count + 1 <= select_max))
return true; return true;
++index; ++index;
...@@ -1341,9 +1366,8 @@ bool ClientField::check_sel_sum_trib_s(const std::set<ClientCard*>& left, int in ...@@ -1341,9 +1366,8 @@ bool ClientField::check_sel_sum_trib_s(const std::set<ClientCard*>& left, int in
check_sel_sum_trib_t(left, acc); check_sel_sum_trib_t(left, acc);
return acc >= select_min && acc <= select_max; return acc >= select_min && acc <= select_max;
} }
int l = selected_cards[index]->opParam; int l1, l2;
int l1 = l & 0xffff; get_sum_params(selected_cards[index]->opParam, l1, l2);
int l2 = l >> 16;
bool res1 = false, res2 = false; bool res1 = false, res2 = false;
res1 = check_sel_sum_trib_s(left, index + 1, acc + l1); res1 = check_sel_sum_trib_s(left, index + 1, acc + l1);
if(l2 > 0) if(l2 > 0)
...@@ -1356,9 +1380,8 @@ void ClientField::check_sel_sum_trib_t(const std::set<ClientCard*>& left, int ac ...@@ -1356,9 +1380,8 @@ void ClientField::check_sel_sum_trib_t(const std::set<ClientCard*>& left, int ac
continue; continue;
std::set<ClientCard*> testlist(left); std::set<ClientCard*> testlist(left);
testlist.erase(*sit); testlist.erase(*sit);
int l = (*sit)->opParam; int l1, l2;
int l1 = l & 0xffff; get_sum_params((*sit)->opParam, l1, l2);
int l2 = l >> 16;
if(check_sum_trib(testlist.begin(), testlist.end(), acc + l1) if(check_sum_trib(testlist.begin(), testlist.end(), acc + l1)
|| (l2 > 0 && check_sum_trib(testlist.begin(), testlist.end(), acc + l2))) { || (l2 > 0 && check_sum_trib(testlist.begin(), testlist.end(), acc + l2))) {
selectsum_cards.insert(*sit); selectsum_cards.insert(*sit);
...@@ -1370,9 +1393,8 @@ bool ClientField::check_sum_trib(std::set<ClientCard*>::const_iterator index, st ...@@ -1370,9 +1393,8 @@ bool ClientField::check_sum_trib(std::set<ClientCard*>::const_iterator index, st
return true; return true;
if(acc > select_max || index == end) if(acc > select_max || index == end)
return false; return false;
int l = (*index)->opParam; int l1, l2;
int l1 = l & 0xffff; get_sum_params((*index)->opParam, l1, l2);
int l2 = l >> 16;
if((acc + l1 >= select_min && acc + l1 <= select_max) || (acc + l2 >= select_min && acc + l2 <= select_max)) if((acc + l1 >= select_min && acc + l1 <= select_max) || (acc + l2 >= select_min && acc + l2 <= select_max))
return true; return true;
++index; ++index;
...@@ -1380,7 +1402,8 @@ bool ClientField::check_sum_trib(std::set<ClientCard*>::const_iterator index, st ...@@ -1380,7 +1402,8 @@ bool ClientField::check_sum_trib(std::set<ClientCard*>::const_iterator index, st
|| check_sum_trib(index, end, acc + l2) || check_sum_trib(index, end, acc + l2)
|| check_sum_trib(index, end, acc); || check_sum_trib(index, end, acc);
} }
static bool is_declarable(const CardData& cd, const std::vector<unsigned int>& opcode) { template <class T>
static bool is_declarable(const T& cd, const std::vector<unsigned int>& opcode) {
std::stack<int> stack; std::stack<int> stack;
for(auto it = opcode.begin(); it != opcode.end(); ++it) { for(auto it = opcode.begin(); it != opcode.end(); ++it) {
switch(*it) { switch(*it) {
...@@ -1470,9 +1493,15 @@ static bool is_declarable(const CardData& cd, const std::vector<unsigned int>& o ...@@ -1470,9 +1493,15 @@ static bool is_declarable(const CardData& cd, const std::vector<unsigned int>& o
} }
case OPCODE_ISSETCARD: { case OPCODE_ISSETCARD: {
if (stack.size() >= 1) { if (stack.size() >= 1) {
int set_code = stack.top(); uint32_t set_code = stack.top();
stack.pop(); stack.pop();
bool res = cd.is_setcode(set_code); bool res = false;
for (const auto& x : cd.setcode) {
if(check_setcode(x, set_code)) {
res = true;
break;
}
}
stack.push(res); stack.push(res);
} }
break; break;
...@@ -1516,12 +1545,12 @@ static bool is_declarable(const CardData& cd, const std::vector<unsigned int>& o ...@@ -1516,12 +1545,12 @@ static bool is_declarable(const CardData& cd, const std::vector<unsigned int>& o
void ClientField::UpdateDeclarableList() { void ClientField::UpdateDeclarableList() {
const wchar_t* pname = mainGame->ebANCard->getText(); const wchar_t* pname = mainGame->ebANCard->getText();
int trycode = BufferIO::GetVal(pname); int trycode = BufferIO::GetVal(pname);
CardString cstr;
CardData cd; CardData cd;
if(dataManager.GetString(trycode, &cstr) && dataManager.GetData(trycode, &cd) && is_declarable(cd, declare_opcodes)) { if (dataManager.GetData(trycode, &cd) && is_declarable(cd, declare_opcodes)) {
auto it = dataManager.GetStringPointer(trycode);
mainGame->lstANCard->clear(); mainGame->lstANCard->clear();
ancard.clear(); ancard.clear();
mainGame->lstANCard->addItem(cstr.name.c_str()); mainGame->lstANCard->addItem(it->second.name.c_str());
ancard.push_back(trycode); ancard.push_back(trycode);
return; return;
} }
......
...@@ -119,6 +119,7 @@ public: ...@@ -119,6 +119,7 @@ public:
bool ShowSelectSum(bool panelmode); bool ShowSelectSum(bool panelmode);
bool CheckSelectSum(); bool CheckSelectSum();
bool CheckSelectTribute(); bool CheckSelectTribute();
void get_sum_params(unsigned int opParam, int& op1, int& op2);
bool check_min(const std::set<ClientCard*>& left, std::set<ClientCard*>::const_iterator index, int min, int max); bool check_min(const std::set<ClientCard*>& left, std::set<ClientCard*>::const_iterator index, int min, int max);
bool check_sel_sum_s(const std::set<ClientCard*>& left, int index, int acc); bool check_sel_sum_s(const std::set<ClientCard*>& left, int index, int acc);
void check_sel_sum_t(const std::set<ClientCard*>& left, int acc); void check_sel_sum_t(const std::set<ClientCard*>& left, int acc);
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <windows.h> #include <windows.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#if defined(_MSC_VER) or defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#define mywcsncasecmp _wcsnicmp #define mywcsncasecmp _wcsnicmp
#define mystrncasecmp _strnicmp #define mystrncasecmp _strnicmp
#else #else
......
...@@ -15,69 +15,63 @@ DataManager::DataManager() : _datas(32768), _strings(32768) { ...@@ -15,69 +15,63 @@ DataManager::DataManager() : _datas(32768), _strings(32768) {
bool DataManager::ReadDB(sqlite3* pDB) { bool DataManager::ReadDB(sqlite3* pDB) {
sqlite3_stmt* pStmt = nullptr; sqlite3_stmt* pStmt = nullptr;
const char* sql = "select * from datas,texts where datas.id=texts.id"; const char* sql = "select * from datas,texts where datas.id=texts.id";
if (sqlite3_prepare_v2(pDB, sql, -1, &pStmt, 0) != SQLITE_OK) if (sqlite3_prepare_v2(pDB, sql, -1, &pStmt, nullptr) != SQLITE_OK)
return Error(pDB, pStmt); return Error(pDB, pStmt);
wchar_t strBuffer[4096]; wchar_t strBuffer[4096];
int step = 0; for (int step = sqlite3_step(pStmt); step != SQLITE_DONE; step = sqlite3_step(pStmt)) {
do { if (step != SQLITE_ROW)
CardDataC cd; return Error(pDB, pStmt);
CardString cs; uint32_t code = static_cast<uint32_t>(sqlite3_column_int64(pStmt, 0));
step = sqlite3_step(pStmt); auto& cd = _datas[code];
if (step == SQLITE_ROW) { cd.code = code;
cd.code = sqlite3_column_int(pStmt, 0); cd.ot = sqlite3_column_int(pStmt, 1);
cd.ot = sqlite3_column_int(pStmt, 1); cd.alias = sqlite3_column_int(pStmt, 2);
cd.alias = sqlite3_column_int(pStmt, 2); uint64_t setcode = static_cast<uint64_t>(sqlite3_column_int64(pStmt, 3));
uint64_t setcode = static_cast<uint64_t>(sqlite3_column_int64(pStmt, 3)); write_setcode(cd.setcode, setcode);
if (setcode) { cd.type = static_cast<decltype(cd.type)>(sqlite3_column_int64(pStmt, 4));
auto it = extra_setcode.find(cd.code); cd.attack = sqlite3_column_int(pStmt, 5);
if (it != extra_setcode.end()) { cd.defense = sqlite3_column_int(pStmt, 6);
int len = it->second.size(); if (cd.type & TYPE_LINK) {
if (len > SIZE_SETCODE) cd.link_marker = cd.defense;
len = SIZE_SETCODE; cd.defense = 0;
if (len) }
std::memcpy(cd.setcode, it->second.data(), len * sizeof(uint16_t)); else
} cd.link_marker = 0;
else uint32_t level = static_cast<uint32_t>(sqlite3_column_int64(pStmt, 7));
cd.set_setcode(setcode); cd.level = level & 0xff;
} cd.lscale = (level >> 24) & 0xff;
cd.type = static_cast<decltype(cd.type)>(sqlite3_column_int64(pStmt, 4)); cd.rscale = (level >> 16) & 0xff;
cd.attack = sqlite3_column_int(pStmt, 5); cd.race = static_cast<decltype(cd.race)>(sqlite3_column_int64(pStmt, 8));
cd.defense = sqlite3_column_int(pStmt, 6); cd.attribute = static_cast<decltype(cd.attribute)>(sqlite3_column_int64(pStmt, 9));
if (cd.type & TYPE_LINK) { cd.category = static_cast<decltype(cd.category)>(sqlite3_column_int64(pStmt, 10));
cd.link_marker = cd.defense; auto& cs = _strings[code];
cd.defense = 0; if (const char* text = (const char*)sqlite3_column_text(pStmt, 12)) {
} BufferIO::DecodeUTF8(text, strBuffer);
else cs.name = strBuffer;
cd.link_marker = 0; }
uint32_t level = static_cast<uint32_t>(sqlite3_column_int(pStmt, 7)); if (const char* text = (const char*)sqlite3_column_text(pStmt, 13)) {
cd.level = level & 0xff; BufferIO::DecodeUTF8(text, strBuffer);
cd.lscale = (level >> 24) & 0xff; cs.text = strBuffer;
cd.rscale = (level >> 16) & 0xff; }
cd.race = static_cast<decltype(cd.race)>(sqlite3_column_int64(pStmt, 8)); constexpr int desc_count = sizeof cs.desc / sizeof cs.desc[0];
cd.attribute = static_cast<decltype(cd.attribute)>(sqlite3_column_int64(pStmt, 9)); for (int i = 0; i < desc_count; ++i) {
cd.category = static_cast<decltype(cd.category)>(sqlite3_column_int64(pStmt, 10)); if (const char* text = (const char*)sqlite3_column_text(pStmt, i + 14)) {
_datas[cd.code] = cd;
if (const char* text = (const char*)sqlite3_column_text(pStmt, 12)) {
BufferIO::DecodeUTF8(text, strBuffer);
cs.name = strBuffer;
}
if (const char* text = (const char*)sqlite3_column_text(pStmt, 13)) {
BufferIO::DecodeUTF8(text, strBuffer); BufferIO::DecodeUTF8(text, strBuffer);
cs.text = strBuffer; cs.desc[i] = strBuffer;
}
constexpr int desc_count = sizeof cs.desc / sizeof cs.desc[0];
for (int i = 0; i < desc_count; ++i) {
if (const char* text = (const char*)sqlite3_column_text(pStmt, i + 14)) {
BufferIO::DecodeUTF8(text, strBuffer);
cs.desc[i] = strBuffer;
}
} }
_strings[cd.code] = cs;
} }
else if (step != SQLITE_DONE) }
return Error(pDB, pStmt);
} while (step == SQLITE_ROW);
sqlite3_finalize(pStmt); sqlite3_finalize(pStmt);
for (const auto& entry : extra_setcode) {
const auto& code = entry.first;
const auto& list = entry.second;
if (list.size() > SIZE_SETCODE || list.empty())
continue;
auto it = _datas.find(code);
if (it == _datas.end())
continue;
std::memcpy(it->second.setcode, list.data(), list.size() * sizeof(uint16_t));
}
return true; return true;
} }
bool DataManager::LoadDB(const wchar_t* wfile) { bool DataManager::LoadDB(const wchar_t* wfile) {
...@@ -165,39 +159,29 @@ void DataManager::ReadStringConfLine(const char* linebuf) { ...@@ -165,39 +159,29 @@ void DataManager::ReadStringConfLine(const char* linebuf) {
} }
} }
bool DataManager::Error(sqlite3* pDB, sqlite3_stmt* pStmt) { bool DataManager::Error(sqlite3* pDB, sqlite3_stmt* pStmt) {
std::snprintf(errmsg, sizeof errmsg, "%s", sqlite3_errmsg(pDB)); if (const char* msg = sqlite3_errmsg(pDB))
if(pStmt) std::snprintf(errmsg, sizeof errmsg, "%s", msg);
sqlite3_finalize(pStmt); else
errmsg[0] = '\0';
sqlite3_finalize(pStmt);
return false; return false;
} }
code_pointer DataManager::GetCodePointer(unsigned int code) const { code_pointer DataManager::GetCodePointer(uint32_t code) const {
return _datas.find(code); return _datas.find(code);
} }
string_pointer DataManager::GetStringPointer(unsigned int code) const { string_pointer DataManager::GetStringPointer(uint32_t code) const {
return _strings.find(code); return _strings.find(code);
} }
code_pointer DataManager::datas_begin() const { bool DataManager::GetData(uint32_t code, CardData* pData) const {
return _datas.cbegin();
}
code_pointer DataManager::datas_end() const {
return _datas.cend();
}
string_pointer DataManager::strings_begin() const {
return _strings.cbegin();
}
string_pointer DataManager::strings_end() const {
return _strings.cend();
}
bool DataManager::GetData(unsigned int code, CardData* pData) const {
auto cdit = _datas.find(code); auto cdit = _datas.find(code);
if(cdit == _datas.end()) if(cdit == _datas.end())
return false; return false;
if (pData) { if (pData) {
*pData = cdit->second; std::memcpy(pData, &cdit->second, sizeof(CardData));
} }
return true; return true;
} }
bool DataManager::GetString(unsigned int code, CardString* pStr) const { bool DataManager::GetString(uint32_t code, CardString* pStr) const {
auto csit = _strings.find(code); auto csit = _strings.find(code);
if(csit == _strings.end()) { if(csit == _strings.end()) {
pStr->name = unknown_string; pStr->name = unknown_string;
...@@ -207,7 +191,7 @@ bool DataManager::GetString(unsigned int code, CardString* pStr) const { ...@@ -207,7 +191,7 @@ bool DataManager::GetString(unsigned int code, CardString* pStr) const {
*pStr = csit->second; *pStr = csit->second;
return true; return true;
} }
const wchar_t* DataManager::GetName(unsigned int code) const { const wchar_t* DataManager::GetName(uint32_t code) const {
auto csit = _strings.find(code); auto csit = _strings.find(code);
if(csit == _strings.end()) if(csit == _strings.end())
return unknown_string; return unknown_string;
...@@ -215,7 +199,7 @@ const wchar_t* DataManager::GetName(unsigned int code) const { ...@@ -215,7 +199,7 @@ const wchar_t* DataManager::GetName(unsigned int code) const {
return csit->second.name.c_str(); return csit->second.name.c_str();
return unknown_string; return unknown_string;
} }
const wchar_t* DataManager::GetText(unsigned int code) const { const wchar_t* DataManager::GetText(uint32_t code) const {
auto csit = _strings.find(code); auto csit = _strings.find(code);
if(csit == _strings.end()) if(csit == _strings.end())
return unknown_string; return unknown_string;
...@@ -223,7 +207,7 @@ const wchar_t* DataManager::GetText(unsigned int code) const { ...@@ -223,7 +207,7 @@ const wchar_t* DataManager::GetText(unsigned int code) const {
return csit->second.text.c_str(); return csit->second.text.c_str();
return unknown_string; return unknown_string;
} }
const wchar_t* DataManager::GetDesc(unsigned int strCode) const { const wchar_t* DataManager::GetDesc(uint32_t strCode) const {
if (strCode < (MIN_CARD_ID << 4)) if (strCode < (MIN_CARD_ID << 4))
return GetSysString(strCode); return GetSysString(strCode);
unsigned int code = (strCode >> 4) & 0x0fffffff; unsigned int code = (strCode >> 4) & 0x0fffffff;
......
...@@ -16,18 +16,34 @@ namespace irr { ...@@ -16,18 +16,34 @@ namespace irr {
namespace ygo { namespace ygo {
constexpr int MAX_STRING_ID = 0x7ff; constexpr int MAX_STRING_ID = 0x7ff;
constexpr unsigned int MIN_CARD_ID = (unsigned int)(MAX_STRING_ID + 1) >> 4; constexpr uint32_t MIN_CARD_ID = (uint32_t)(MAX_STRING_ID + 1) >> 4;
constexpr unsigned int MAX_CARD_ID = 0x0fffffffU; constexpr uint32_t MAX_CARD_ID = 0x0fffffffU;
using CardData = card_data; using CardData = card_data;
struct CardDataC : card_data { struct CardDataC {
uint32_t code{};
uint32_t alias{};
uint16_t setcode[SIZE_SETCODE]{};
uint32_t type{};
uint32_t level{};
uint32_t attribute{};
uint32_t race{};
int32_t attack{};
int32_t defense{};
uint32_t lscale{};
uint32_t rscale{};
uint32_t link_marker{};
uint32_t ot{}; uint32_t ot{};
uint32_t category{}; uint32_t category{};
bool is_setcodes(const std::vector<unsigned int>& values) const { bool is_setcodes(const std::vector<unsigned int>& values) const {
for (auto& value : values) { for (auto& value : values) {
if (is_setcode(value)) for (const auto& x : setcode) {
return true; if(!x)
break;
if(check_setcode(x, value))
return true;
}
} }
return false; return false;
} }
...@@ -37,8 +53,8 @@ struct CardString { ...@@ -37,8 +53,8 @@ struct CardString {
std::wstring text; std::wstring text;
std::wstring desc[16]; std::wstring desc[16];
}; };
using code_pointer = std::unordered_map<unsigned int, CardDataC>::const_iterator; using code_pointer = std::unordered_map<uint32_t, CardDataC>::const_iterator;
using string_pointer = std::unordered_map<unsigned int, CardString>::const_iterator; using string_pointer = std::unordered_map<uint32_t, CardString>::const_iterator;
class DataManager { class DataManager {
public: public:
...@@ -50,17 +66,25 @@ public: ...@@ -50,17 +66,25 @@ public:
void ReadStringConfLine(const char* linebuf); void ReadStringConfLine(const char* linebuf);
bool Error(sqlite3* pDB, sqlite3_stmt* pStmt = nullptr); bool Error(sqlite3* pDB, sqlite3_stmt* pStmt = nullptr);
code_pointer GetCodePointer(unsigned int code) const; code_pointer GetCodePointer(uint32_t code) const;
string_pointer GetStringPointer(unsigned int code) const; string_pointer GetStringPointer(uint32_t code) const;
code_pointer datas_begin() const; code_pointer datas_begin() const noexcept {
code_pointer datas_end() const; return _datas.cbegin();
string_pointer strings_begin() const; }
string_pointer strings_end() const; code_pointer datas_end() const noexcept {
bool GetData(unsigned int code, CardData* pData) const; return _datas.cend();
bool GetString(unsigned int code, CardString* pStr) const; }
const wchar_t* GetName(unsigned int code) const; string_pointer strings_begin() const noexcept {
const wchar_t* GetText(unsigned int code) const; return _strings.cbegin();
const wchar_t* GetDesc(unsigned int strCode) const; }
string_pointer strings_end() const noexcept {
return _strings.cend();
}
bool GetData(uint32_t code, CardData* pData) const;
bool GetString(uint32_t code, CardString* pStr) const;
const wchar_t* GetName(uint32_t code) const;
const wchar_t* GetText(uint32_t code) const;
const wchar_t* GetDesc(uint32_t strCode) const;
const wchar_t* GetSysString(int code) const; const wchar_t* GetSysString(int code) const;
const wchar_t* GetVictoryString(int code) const; const wchar_t* GetVictoryString(int code) const;
const wchar_t* GetCounterName(int code) const; const wchar_t* GetCounterName(int code) const;
...@@ -98,9 +122,9 @@ public: ...@@ -98,9 +122,9 @@ 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:
std::unordered_map<unsigned int, CardDataC> _datas; std::unordered_map<uint32_t, CardDataC> _datas;
std::unordered_map<unsigned int, CardString> _strings; std::unordered_map<uint32_t, CardString> _strings;
std::unordered_map<unsigned int, std::vector<uint16_t>> extra_setcode; std::unordered_map<uint32_t, std::vector<uint16_t>> extra_setcode;
}; };
extern DataManager dataManager; extern DataManager dataManager;
......
...@@ -696,16 +696,16 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -696,16 +696,16 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
break; break;
} }
mainGame->ClearCardInfo(); mainGame->ClearCardInfo();
unsigned char deckbuf[1024]; unsigned char deckbuf[1024]{};
auto pdeck = deckbuf; auto pdeck = deckbuf;
BufferIO::WriteInt32(pdeck, deckManager.current_deck.main.size() + deckManager.current_deck.extra.size()); BufferIO::Write<int32_t>(pdeck, static_cast<int32_t>(deckManager.current_deck.main.size() + deckManager.current_deck.extra.size()));
BufferIO::WriteInt32(pdeck, deckManager.current_deck.side.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) for(size_t i = 0; i < deckManager.current_deck.main.size(); ++i)
BufferIO::WriteInt32(pdeck, deckManager.current_deck.main[i]->first); BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.main[i]->first);
for(size_t i = 0; i < deckManager.current_deck.extra.size(); ++i) for(size_t i = 0; i < deckManager.current_deck.extra.size(); ++i)
BufferIO::WriteInt32(pdeck, deckManager.current_deck.extra[i]->first); BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.extra[i]->first);
for(size_t i = 0; i < deckManager.current_deck.side.size(); ++i) for(size_t i = 0; i < deckManager.current_deck.side.size(); ++i)
BufferIO::WriteInt32(pdeck, deckManager.current_deck.side[i]->first); BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.side[i]->first);
DuelClient::SendBufferToServer(CTOS_UPDATE_DECK, deckbuf, pdeck - deckbuf); DuelClient::SendBufferToServer(CTOS_UPDATE_DECK, deckbuf, pdeck - deckbuf);
break; break;
} }
...@@ -1472,7 +1472,7 @@ void DeckBuilder::FilterCards() { ...@@ -1472,7 +1472,7 @@ void DeckBuilder::FilterCards() {
auto strpointer = dataManager.GetStringPointer(ptr->first); auto strpointer = dataManager.GetStringPointer(ptr->first);
if (strpointer == dataManager.strings_end()) if (strpointer == dataManager.strings_end())
continue; continue;
const CardString& text = strpointer->second; const CardString& strings = strpointer->second;
if(data.type & TYPE_TOKEN) if(data.type & TYPE_TOKEN)
continue; continue;
switch(filter_type) { switch(filter_type) {
...@@ -1548,14 +1548,14 @@ void DeckBuilder::FilterCards() { ...@@ -1548,14 +1548,14 @@ void DeckBuilder::FilterCards() {
for (auto elements_iterator = query_elements.begin(); elements_iterator != query_elements.end(); ++elements_iterator) { for (auto elements_iterator = query_elements.begin(); elements_iterator != query_elements.end(); ++elements_iterator) {
bool match = false; bool match = false;
if (elements_iterator->type == element_t::type_t::name) { if (elements_iterator->type == element_t::type_t::name) {
match = CardNameContains(text.name.c_str(), elements_iterator->keyword.c_str()); match = CardNameContains(strings.name.c_str(), elements_iterator->keyword.c_str());
} else if (elements_iterator->type == element_t::type_t::setcode) { } else if (elements_iterator->type == element_t::type_t::setcode) {
match = data.is_setcodes(elements_iterator->setcodes); match = data.is_setcodes(elements_iterator->setcodes);
} else if (trycode && (data.code == trycode || data.alias == trycode && data.is_alternative())){ } else if (trycode && (data.code == trycode || data.alias == trycode && is_alternative(data.code, data.alias))){
match = true; match = true;
} else { } else {
match = CardNameContains(text.name.c_str(), elements_iterator->keyword.c_str()) match = CardNameContains(strings.name.c_str(), elements_iterator->keyword.c_str())
|| text.text.find(elements_iterator->keyword) != std::wstring::npos || strings.text.find(elements_iterator->keyword) != std::wstring::npos
|| data.is_setcodes(elements_iterator->setcodes); || data.is_setcodes(elements_iterator->setcodes);
} }
if(elements_iterator->exclude) if(elements_iterator->exclude)
...@@ -1871,7 +1871,7 @@ void DeckBuilder::pop_side(int seq) { ...@@ -1871,7 +1871,7 @@ void DeckBuilder::pop_side(int seq) {
GetHoveredCard(); GetHoveredCard();
} }
bool DeckBuilder::check_limit(code_pointer pointer) { bool DeckBuilder::check_limit(code_pointer pointer) {
unsigned int limitcode = pointer->second.alias ? pointer->second.alias : pointer->first; auto limitcode = pointer->second.alias ? pointer->second.alias : pointer->first;
int limit = 3; int limit = 3;
auto flit = filterList->content.find(limitcode); auto flit = filterList->content.find(limitcode);
if(flit != filterList->content.end()) if(flit != filterList->content.end())
......
...@@ -13,7 +13,6 @@ void DeckManager::LoadLFListSingle(const char* path) { ...@@ -13,7 +13,6 @@ void DeckManager::LoadLFListSingle(const char* path) {
FILE* fp = myfopen(path, "r"); FILE* fp = myfopen(path, "r");
char linebuf[256]{}; char linebuf[256]{};
wchar_t strBuffer[256]{}; wchar_t strBuffer[256]{};
char str1[16]{};
if(fp) { if(fp) {
while(std::fgets(linebuf, sizeof linebuf, fp)) { while(std::fgets(linebuf, sizeof linebuf, fp)) {
if(linebuf[0] == '#') if(linebuf[0] == '#')
...@@ -31,13 +30,20 @@ void DeckManager::LoadLFListSingle(const char* path) { ...@@ -31,13 +30,20 @@ void DeckManager::LoadLFListSingle(const char* path) {
} }
if (cur == _lfList.rend()) if (cur == _lfList.rend())
continue; continue;
unsigned int code = 0; char* pos = linebuf;
int count = -1; errno = 0;
if (std::sscanf(linebuf, "%10s%*[ ]%1d", str1, &count) != 2) auto result = std::strtoul(pos, &pos, 10);
if (errno || result > UINT32_MAX)
continue;
if (pos == linebuf || *pos != ' ')
continue;
uint32_t code = static_cast<uint32_t>(result);
errno = 0;
int count = std::strtol(pos, &pos, 10);
if (errno)
continue; continue;
if (count < 0 || count > 2) if (count < 0 || count > 2)
continue; continue;
code = std::strtoul(str1, nullptr, 10);
cur->content[code] = count; cur->content[code] = count;
cur->hash = cur->hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + count)) | (code >> (5 - count))); cur->hash = cur->hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + count)) | (code >> (5 - count)));
} }
...@@ -196,8 +202,9 @@ uint32_t DeckManager::LoadDeckFromStream(Deck& deck, std::istringstream& deckStr ...@@ -196,8 +202,9 @@ uint32_t DeckManager::LoadDeckFromStream(Deck& deck, std::istringstream& deckStr
} }
if (linebuf[0] < '0' || linebuf[0] > '9') if (linebuf[0] < '0' || linebuf[0] > '9')
continue; continue;
errno = 0;
auto code = std::strtoul(linebuf.c_str(), nullptr, 10); auto code = std::strtoul(linebuf.c_str(), nullptr, 10);
if (code >= UINT32_MAX) if (errno || code > UINT32_MAX)
continue; continue;
cardlist[ct++] = code; cardlist[ct++] = code;
if (is_side) if (is_side)
......
...@@ -13,10 +13,13 @@ namespace ygo { ...@@ -13,10 +13,13 @@ namespace ygo {
constexpr int SIDE_MAX_SIZE = 15; constexpr int SIDE_MAX_SIZE = 15;
constexpr int PACK_MAX_SIZE = 1000; constexpr int PACK_MAX_SIZE = 1000;
constexpr int MAINC_MAX = 250; // the limit of card_state
constexpr int SIDEC_MAX = MAINC_MAX;
struct LFList { struct LFList {
unsigned int hash{}; unsigned int hash{};
std::wstring listName; std::wstring listName;
std::unordered_map<unsigned int, int> content; std::unordered_map<uint32_t, int> content;
}; };
struct Deck { struct Deck {
std::vector<code_pointer> main; std::vector<code_pointer> main;
......
...@@ -1121,7 +1121,7 @@ void Game::WaitFrameSignal(int frame) { ...@@ -1121,7 +1121,7 @@ void Game::WaitFrameSignal(int frame) {
frameSignal.Wait(); frameSignal.Wait();
} }
void Game::DrawThumb(code_pointer cp, irr::core::vector2di pos, const LFList* lflist, bool drag) { void Game::DrawThumb(code_pointer cp, irr::core::vector2di pos, const LFList* lflist, bool drag) {
int code = cp->first; auto code = cp->first;
auto lcode = cp->second.alias; auto lcode = cp->second.alias;
if(lcode == 0) if(lcode == 0)
lcode = code; lcode = code;
......
This diff is collapsed.
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <vector> #include <vector>
#include <set> #include <set>
#include <random> #include <random>
#include "config.h"
#include "network.h" #include "network.h"
namespace ygo { namespace ygo {
...@@ -49,16 +50,16 @@ public: ...@@ -49,16 +50,16 @@ public:
static void SendResponse(); static void SendResponse();
static void SendPacketToServer(unsigned char proto) { static void SendPacketToServer(unsigned char proto) {
auto p = duel_client_write; auto p = duel_client_write;
buffer_write<uint16_t>(p, 1); BufferIO::Write<uint16_t>(p, 1);
buffer_write<uint8_t>(p, proto); BufferIO::Write<uint8_t>(p, proto);
bufferevent_write(client_bev, duel_client_write, 3); bufferevent_write(client_bev, duel_client_write, 3);
} }
template<typename ST> template<typename ST>
static void SendPacketToServer(unsigned char proto, const ST& st) { static void SendPacketToServer(unsigned char proto, const ST& st) {
auto p = duel_client_write; auto p = duel_client_write;
static_assert(sizeof(ST) <= MAX_DATA_SIZE, "Packet size is too large."); static_assert(sizeof(ST) <= MAX_DATA_SIZE, "Packet size is too large.");
buffer_write<uint16_t>(p, (uint16_t)(1 + sizeof(ST))); BufferIO::Write<uint16_t>(p, (uint16_t)(1 + sizeof(ST)));
buffer_write<uint8_t>(p, proto); BufferIO::Write<uint8_t>(p, proto);
std::memcpy(p, &st, sizeof(ST)); std::memcpy(p, &st, sizeof(ST));
bufferevent_write(client_bev, duel_client_write, sizeof(ST) + 3); bufferevent_write(client_bev, duel_client_write, sizeof(ST) + 3);
} }
...@@ -66,8 +67,8 @@ public: ...@@ -66,8 +67,8 @@ public:
auto p = duel_client_write; auto p = duel_client_write;
if (len > MAX_DATA_SIZE) if (len > MAX_DATA_SIZE)
len = MAX_DATA_SIZE; len = MAX_DATA_SIZE;
buffer_write<uint16_t>(p, (uint16_t)(1 + len)); BufferIO::Write<uint16_t>(p, (uint16_t)(1 + len));
buffer_write<uint8_t>(p, proto); BufferIO::Write<uint8_t>(p, proto);
std::memcpy(p, buffer, len); std::memcpy(p, buffer, len);
bufferevent_write(client_bev, duel_client_write, len + 3); bufferevent_write(client_bev, duel_client_write, len + 3);
} }
......
...@@ -375,9 +375,9 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -375,9 +375,9 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
select_options_index.clear(); select_options_index.clear();
for (size_t i = 0; i < activatable_cards.size(); ++i) { for (size_t i = 0; i < activatable_cards.size(); ++i) {
if (activatable_cards[i] == menu_card) { if (activatable_cards[i] == menu_card) {
if(activatable_descs[i].second == EDESC_OPERATION) if(activatable_descs[i].second & EDESC_OPERATION)
continue; continue;
else if(activatable_descs[i].second == EDESC_RESET) { else if(activatable_descs[i].second & EDESC_RESET) {
if(id == BUTTON_CMD_ACTIVATE) continue; if(id == BUTTON_CMD_ACTIVATE) continue;
} else { } else {
if(id == BUTTON_CMD_RESET) continue; if(id == BUTTON_CMD_RESET) continue;
...@@ -658,7 +658,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -658,7 +658,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
select_options_index.clear(); select_options_index.clear();
for (size_t i = 0; i < activatable_cards.size(); ++i) { for (size_t i = 0; i < activatable_cards.size(); ++i) {
if (activatable_cards[i] == command_card) { if (activatable_cards[i] == command_card) {
if(activatable_descs[i].second == EDESC_OPERATION) { if(activatable_descs[i].second & EDESC_OPERATION) {
if(list_command == COMMAND_ACTIVATE) continue; if(list_command == COMMAND_ACTIVATE) continue;
} else { } else {
if(list_command == COMMAND_OPERATION) continue; if(list_command == COMMAND_OPERATION) continue;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "single_mode.h" #include "single_mode.h"
#include <thread> #include <thread>
const unsigned short PRO_VERSION = 0x1361; const unsigned short PRO_VERSION = 0x1362;
namespace ygo { namespace ygo {
...@@ -1234,11 +1234,8 @@ void Game::RefreshDeck(const wchar_t* deckpath, const std::function<void(const w ...@@ -1234,11 +1234,8 @@ void Game::RefreshDeck(const wchar_t* deckpath, const std::function<void(const w
} }
FileSystem::TraversalDir(deckpath, [additem](const wchar_t* name, bool isdir) { FileSystem::TraversalDir(deckpath, [additem](const wchar_t* name, bool isdir) {
if (!isdir && IsExtension(name, L".ydk")) { if (!isdir && IsExtension(name, L".ydk")) {
size_t len = std::wcslen(name);
wchar_t deckname[256]{}; wchar_t deckname[256]{};
size_t count = std::min(len - 4, sizeof deckname / sizeof deckname[0] - 1); BufferIO::CopyWideString(name, deckname, std::wcslen(name) - 4);
std::wcsncpy(deckname, name, count);
deckname[count] = 0;
additem(deckname); additem(deckname);
} }
}); });
...@@ -1544,7 +1541,7 @@ void Game::ShowCardInfo(int code, bool resize) { ...@@ -1544,7 +1541,7 @@ void Game::ShowCardInfo(int code, bool resize) {
imgCard->setImage(imageManager.GetTexture(code, true)); imgCard->setImage(imageManager.GetTexture(code, true));
if (is_valid) { if (is_valid) {
auto& cd = cit->second; auto& cd = cit->second;
if (cd.is_alternative()) if (is_alternative(cd.code,cd.alias))
myswprintf(formatBuffer, L"%ls[%08d]", dataManager.GetName(cd.alias), cd.alias); myswprintf(formatBuffer, L"%ls[%08d]", dataManager.GetName(cd.alias), cd.alias);
else else
myswprintf(formatBuffer, L"%ls[%08d]", dataManager.GetName(code), code); myswprintf(formatBuffer, L"%ls[%08d]", dataManager.GetName(code), code);
......
...@@ -17,14 +17,14 @@ void UpdateDeck() { ...@@ -17,14 +17,14 @@ void UpdateDeck() {
BufferIO::CopyWideString(mainGame->cbDeckSelect->getText(), mainGame->gameConf.lastdeck); BufferIO::CopyWideString(mainGame->cbDeckSelect->getText(), mainGame->gameConf.lastdeck);
unsigned char deckbuf[1024]{}; unsigned char deckbuf[1024]{};
auto pdeck = deckbuf; auto pdeck = deckbuf;
BufferIO::WriteInt32(pdeck, deckManager.current_deck.main.size() + deckManager.current_deck.extra.size()); BufferIO::Write<int32_t>(pdeck, static_cast<int32_t>(deckManager.current_deck.main.size() + deckManager.current_deck.extra.size()));
BufferIO::WriteInt32(pdeck, deckManager.current_deck.side.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) for(size_t i = 0; i < deckManager.current_deck.main.size(); ++i)
BufferIO::WriteInt32(pdeck, deckManager.current_deck.main[i]->first); BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.main[i]->first);
for(size_t i = 0; i < deckManager.current_deck.extra.size(); ++i) for(size_t i = 0; i < deckManager.current_deck.extra.size(); ++i)
BufferIO::WriteInt32(pdeck, deckManager.current_deck.extra[i]->first); BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.extra[i]->first);
for(size_t i = 0; i < deckManager.current_deck.side.size(); ++i) for(size_t i = 0; i < deckManager.current_deck.side.size(); ++i)
BufferIO::WriteInt32(pdeck, deckManager.current_deck.side[i]->first); BufferIO::Write<uint32_t>(pdeck, deckManager.current_deck.side[i]->first);
DuelClient::SendBufferToServer(CTOS_UPDATE_DECK, deckbuf, pdeck - deckbuf); DuelClient::SendBufferToServer(CTOS_UPDATE_DECK, deckbuf, pdeck - deckbuf);
} }
bool MenuHandler::OnEvent(const irr::SEvent& event) { bool MenuHandler::OnEvent(const irr::SEvent& event) {
...@@ -234,8 +234,12 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -234,8 +234,12 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
case BUTTON_LOAD_REPLAY: { case BUTTON_LOAD_REPLAY: {
int start_turn = 1; int start_turn = 1;
if(open_file) { if(open_file) {
ReplayMode::cur_replay.OpenReplay(open_file_name);
open_file = false; open_file = false;
if (!ReplayMode::cur_replay.OpenReplay(open_file_name)) {
if (exit_on_return)
mainGame->device->closeDevice();
break;
}
} else { } else {
auto selected = mainGame->lstReplayList->getSelected(); auto selected = mainGame->lstReplayList->getSelected();
if(selected == -1) if(selected == -1)
...@@ -424,8 +428,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -424,8 +428,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
wchar_t *dot = std::wcsrchr(open_file_name, L'.'); wchar_t *dot = std::wcsrchr(open_file_name, L'.');
if(dash && dot && !mywcsncasecmp(dot, L".ydk", 4)) { // full path if(dash && dot && !mywcsncasecmp(dot, L".ydk", 4)) { // full path
wchar_t deck_name[256]; wchar_t deck_name[256];
std::wcsncpy(deck_name, dash + 1, dot - dash - 1); BufferIO::CopyWideString(dash + 1, deck_name, dot - dash - 1);
deck_name[dot - dash - 1] = L'\0';
mainGame->ebDeckname->setText(deck_name); mainGame->ebDeckname->setText(deck_name);
mainGame->cbDBCategory->setSelected(-1); mainGame->cbDBCategory->setSelected(-1);
mainGame->cbDBDecks->setSelected(-1); mainGame->cbDBDecks->setSelected(-1);
...@@ -434,7 +437,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -434,7 +437,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
mainGame->cbDBDecks->setEnabled(false); mainGame->cbDBDecks->setEnabled(false);
} else if(dash) { // has category } else if(dash) { // has category
wchar_t deck_name[256]; wchar_t deck_name[256];
std::wcsncpy(deck_name, dash + 1, 256); BufferIO::CopyWideString(dash + 1, deck_name);
for(size_t i = 0; i < mainGame->cbDBDecks->getItemCount(); ++i) { for(size_t i = 0; i < mainGame->cbDBDecks->getItemCount(); ++i) {
if(!std::wcscmp(mainGame->cbDBDecks->getItem(i), deck_name)) { if(!std::wcscmp(mainGame->cbDBDecks->getItem(i), deck_name)) {
BufferIO::CopyWideString(deck_name, mainGame->gameConf.lastdeck); BufferIO::CopyWideString(deck_name, mainGame->gameConf.lastdeck);
......
...@@ -185,7 +185,7 @@ void NetServer::DisconnectPlayer(DuelPlayer* dp) { ...@@ -185,7 +185,7 @@ void NetServer::DisconnectPlayer(DuelPlayer* dp) {
} }
void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len) { void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len) {
auto pdata = data; auto pdata = data;
unsigned char pktType = BufferIO::ReadUInt8(pdata); unsigned char pktType = BufferIO::Read<uint8_t>(pdata);
if((pktType != CTOS_SURRENDER) && (pktType != CTOS_CHAT) && (dp->state == 0xff || (dp->state && dp->state != pktType))) if((pktType != CTOS_SURRENDER) && (pktType != CTOS_CHAT) && (dp->state == 0xff || (dp->state && dp->state != pktType)))
return; return;
switch(pktType) { switch(pktType) {
...@@ -257,6 +257,15 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len) { ...@@ -257,6 +257,15 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len) {
BufferIO::CopyCharArray(pkt->name, dp->name); BufferIO::CopyCharArray(pkt->name, dp->name);
break; break;
} }
case CTOS_EXTERNAL_ADDRESS: {
// for other server & reverse proxy use only
/*
wchar_t hostname[LEN_HOSTNAME];
uint32_t real_ip = ntohl(BufferIO::Read<int32_t>(pdata));
BufferIO::CopyCharArray((uint16_t*)pdata, hostname);
*/
break;
}
case CTOS_CREATE_GAME: { case CTOS_CREATE_GAME: {
if(dp->game || duel_mode) if(dp->game || duel_mode)
return; return;
...@@ -371,8 +380,9 @@ size_t NetServer::CreateChatPacket(unsigned char* src, int src_size, unsigned ch ...@@ -371,8 +380,9 @@ size_t NetServer::CreateChatPacket(unsigned char* src, int src_size, unsigned ch
return 0; return 0;
// STOC_Chat packet // STOC_Chat packet
auto pdst = dst; auto pdst = dst;
buffer_write<uint16_t>(pdst, dst_player_type); BufferIO::Write<uint16_t>(pdst, dst_player_type);
buffer_write_block(pdst, src_msg, src_size); std::memcpy(pdst, src_msg, src_size);
pdst += src_size;
return sizeof(dst_player_type) + src_size; return sizeof(dst_player_type) + src_size;
} }
......
#ifndef NETSERVER_H #ifndef NETSERVER_H
#define NETSERVER_H #define NETSERVER_H
#include "network.h"
#include <unordered_map> #include <unordered_map>
#include "config.h"
#include "network.h"
namespace ygo { namespace ygo {
...@@ -34,8 +35,8 @@ public: ...@@ -34,8 +35,8 @@ public:
static size_t CreateChatPacket(unsigned char* src, int src_size, unsigned char* dst, uint16_t dst_player_type); static size_t CreateChatPacket(unsigned char* src, int src_size, unsigned char* dst, uint16_t dst_player_type);
static void SendPacketToPlayer(DuelPlayer* dp, unsigned char proto) { static void SendPacketToPlayer(DuelPlayer* dp, unsigned char proto) {
auto p = net_server_write; auto p = net_server_write;
buffer_write<uint16_t>(p, 1); BufferIO::Write<uint16_t>(p, 1);
buffer_write<uint8_t>(p, proto); BufferIO::Write<uint8_t>(p, proto);
last_sent = 3; last_sent = 3;
if (dp) if (dp)
bufferevent_write(dp->bev, net_server_write, 3); bufferevent_write(dp->bev, net_server_write, 3);
...@@ -44,8 +45,8 @@ public: ...@@ -44,8 +45,8 @@ public:
static void SendPacketToPlayer(DuelPlayer* dp, unsigned char proto, const ST& st) { static void SendPacketToPlayer(DuelPlayer* dp, unsigned char proto, const ST& st) {
auto p = net_server_write; auto p = net_server_write;
static_assert(sizeof(ST) <= MAX_DATA_SIZE, "Packet size is too large."); static_assert(sizeof(ST) <= MAX_DATA_SIZE, "Packet size is too large.");
buffer_write<uint16_t>(p, (uint16_t)(1 + sizeof(ST))); BufferIO::Write<uint16_t>(p, (uint16_t)(1 + sizeof(ST)));
buffer_write<uint8_t>(p, proto); BufferIO::Write<uint8_t>(p, proto);
std::memcpy(p, &st, sizeof(ST)); std::memcpy(p, &st, sizeof(ST));
last_sent = sizeof(ST) + 3; last_sent = sizeof(ST) + 3;
if (dp) if (dp)
...@@ -55,8 +56,8 @@ public: ...@@ -55,8 +56,8 @@ public:
auto p = net_server_write; auto p = net_server_write;
if (len > MAX_DATA_SIZE) if (len > MAX_DATA_SIZE)
len = MAX_DATA_SIZE; len = MAX_DATA_SIZE;
buffer_write<uint16_t>(p, (uint16_t)(1 + len)); BufferIO::Write<uint16_t>(p, (uint16_t)(1 + len));
buffer_write<uint8_t>(p, proto); BufferIO::Write<uint8_t>(p, proto);
std::memcpy(p, buffer, len); std::memcpy(p, buffer, len);
last_sent = len + 3; last_sent = len + 3;
if (dp) if (dp)
......
...@@ -9,14 +9,13 @@ ...@@ -9,14 +9,13 @@
#include <event2/buffer.h> #include <event2/buffer.h>
#include <event2/thread.h> #include <event2/thread.h>
#include <type_traits> #include <type_traits>
#include "deck_manager.h"
#define check_trivially_copyable(T) static_assert(std::is_trivially_copyable<T>::value == true && std::is_standard_layout<T>::value == true, "not trivially copyable") #define check_trivially_copyable(T) static_assert(std::is_trivially_copyable<T>::value == true && std::is_standard_layout<T>::value == true, "not trivially copyable")
namespace ygo { namespace ygo {
constexpr int SIZE_NETWORK_BUFFER = 0x20000; constexpr int SIZE_NETWORK_BUFFER = 0x20000;
constexpr int MAX_DATA_SIZE = UINT16_MAX - 1; constexpr int MAX_DATA_SIZE = UINT16_MAX - 1;
constexpr int MAINC_MAX = 250; // the limit of card_state
constexpr int SIDEC_MAX = MAINC_MAX;
struct HostInfo { struct HostInfo {
uint32_t lflist{}; uint32_t lflist{};
...@@ -103,6 +102,14 @@ struct CTOS_Kick { ...@@ -103,6 +102,14 @@ struct CTOS_Kick {
check_trivially_copyable(CTOS_Kick); check_trivially_copyable(CTOS_Kick);
static_assert(sizeof(CTOS_Kick) == 1, "size mismatch: CTOS_Kick"); static_assert(sizeof(CTOS_Kick) == 1, "size mismatch: CTOS_Kick");
/*
* CTOS_ExternalAddress
* uint32_t real_ip; (IPv4 address, BE, alway 0 in normal client)
* uint16_t hostname[256]; (UTF-16 string)
*/
constexpr int LEN_HOSTNAME = 256;
// STOC // STOC
struct STOC_ErrorMsg { struct STOC_ErrorMsg {
uint8_t msg{}; uint8_t msg{};
...@@ -258,6 +265,7 @@ public: ...@@ -258,6 +265,7 @@ public:
#define CTOS_SURRENDER 0x14 // no data #define CTOS_SURRENDER 0x14 // no data
#define CTOS_TIME_CONFIRM 0x15 // no data #define CTOS_TIME_CONFIRM 0x15 // no data
#define CTOS_CHAT 0x16 // uint16_t array #define CTOS_CHAT 0x16 // uint16_t array
#define CTOS_EXTERNAL_ADDRESS 0x17 // CTOS_ExternalAddress
#define CTOS_HS_TODUELIST 0x20 // no data #define CTOS_HS_TODUELIST 0x20 // no data
#define CTOS_HS_TOOBSERVER 0x21 // no data #define CTOS_HS_TOOBSERVER 0x21 // no data
#define CTOS_HS_READY 0x22 // no data #define CTOS_HS_READY 0x22 // no data
......
#include "config.h"
#include "replay.h" #include "replay.h"
#include "myfilesystem.h" #include "myfilesystem.h"
#include "network.h"
#include "lzma/LzmaLib.h" #include "lzma/LzmaLib.h"
namespace ygo { namespace ygo {
...@@ -16,31 +16,18 @@ Replay::~Replay() { ...@@ -16,31 +16,18 @@ Replay::~Replay() {
void Replay::BeginRecord() { void Replay::BeginRecord() {
if(!FileSystem::IsDirExists(L"./replay") && !FileSystem::MakeDir(L"./replay")) if(!FileSystem::IsDirExists(L"./replay") && !FileSystem::MakeDir(L"./replay"))
return; return;
#ifdef _WIN32
if(is_recording)
CloseHandle(recording_fp);
recording_fp = CreateFileW(L"./replay/_LastReplay.yrp", GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, nullptr);
if(recording_fp == INVALID_HANDLE_VALUE)
return;
#else
if(is_recording) if(is_recording)
std::fclose(fp); std::fclose(fp);
fp = myfopen("./replay/_LastReplay.yrp", "wb"); fp = myfopen("./replay/_LastReplay.yrp", "wb");
if(!fp) if(!fp)
return; return;
#endif
Reset(); Reset();
is_recording = true; is_recording = true;
} }
void Replay::WriteHeader(ExtendedReplayHeader& header) { void Replay::WriteHeader(ExtendedReplayHeader& header) {
pheader = header; pheader = header;
#ifdef _WIN32 std::fwrite(&header, sizeof header, 1, fp);
DWORD size;
WriteFile(recording_fp, &header, sizeof(header), &size, nullptr);
#else
std::fwrite(&header, sizeof(header), 1, fp);
std::fflush(fp); std::fflush(fp);
#endif
} }
void Replay::WriteData(const void* data, size_t length, bool flush) { void Replay::WriteData(const void* data, size_t length, bool flush) {
if(!is_recording) if(!is_recording)
...@@ -49,14 +36,9 @@ void Replay::WriteData(const void* data, size_t length, bool flush) { ...@@ -49,14 +36,9 @@ void Replay::WriteData(const void* data, size_t length, bool flush) {
return; return;
std::memcpy(replay_data + replay_size, data, length); std::memcpy(replay_data + replay_size, data, length);
replay_size += length; replay_size += length;
#ifdef _WIN32
DWORD size;
WriteFile(recording_fp, data, length, &size, nullptr);
#else
std::fwrite(data, length, 1, fp); std::fwrite(data, length, 1, fp);
if(flush) if(flush)
std::fflush(fp); std::fflush(fp);
#endif
} }
void Replay::WriteInt32(int32_t data, bool flush) { void Replay::WriteInt32(int32_t data, bool flush) {
Write<int32_t>(data, flush); Write<int32_t>(data, flush);
...@@ -64,19 +46,12 @@ void Replay::WriteInt32(int32_t data, bool flush) { ...@@ -64,19 +46,12 @@ void Replay::WriteInt32(int32_t data, bool flush) {
void Replay::Flush() { void Replay::Flush() {
if(!is_recording) if(!is_recording)
return; return;
#ifdef _WIN32
#else
std::fflush(fp); std::fflush(fp);
#endif
} }
void Replay::EndRecord() { void Replay::EndRecord() {
if(!is_recording) if(!is_recording)
return; return;
#ifdef _WIN32
CloseHandle(recording_fp);
#else
std::fclose(fp); std::fclose(fp);
#endif
pheader.base.datasize = replay_size; pheader.base.datasize = replay_size;
pheader.base.flag |= REPLAY_COMPRESSED; pheader.base.flag |= REPLAY_COMPRESSED;
size_t propsize = 5; size_t propsize = 5;
......
#ifndef REPLAY_H #ifndef REPLAY_H
#define REPLAY_H #define REPLAY_H
#include "config.h" #include <cstdio>
#include <vector>
#include <string>
#include "../ocgcore/ocgapi.h"
#include "deck_manager.h" #include "deck_manager.h"
namespace ygo { namespace ygo {
...@@ -95,10 +98,6 @@ public: ...@@ -95,10 +98,6 @@ public:
bool IsReplaying() const; bool IsReplaying() const;
FILE* fp{ nullptr }; FILE* fp{ nullptr };
#ifdef _WIN32
HANDLE recording_fp{ nullptr };
#endif
ExtendedReplayHeader pheader; ExtendedReplayHeader pheader;
unsigned char* comp_data; unsigned char* comp_data;
size_t comp_size{}; size_t comp_size{};
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Subproject commit 2c75497923afa6d7e6097cc31ecc3f7f96dc3b8b Subproject commit e5ce3178a7d78d3d31de0ef40993cb83b34772ce
project "event" project "event"
kind "StaticLib" kind "StaticLib"
local EVENT_VERSION = (io.readfile("configure") or ""):match("NUMERIC_VERSION%s+0x(%x+)") local EVENT_VERSION = (io.readfile("configure") or ""):match("NUMERIC_VERSION%s+(0x%x+)")
if not EVENT_VERSION then if not EVENT_VERSION then
print("Warning: Could not determine libevent version from the configure file, assuming 2.1.12.") print("Warning: Could not determine libevent version from the configure file, assuming 2.1.12.")
EVENT_VERSION = "02010c00" -- 2.1.12 EVENT_VERSION = "0x02010c00" -- 2.1.12
end end
EVENT_VERSION = tonumber(EVENT_VERSION, 16) EVENT_VERSION = tonumber(EVENT_VERSION)
if EVENT_VERSION>=0x02020000 then if EVENT_VERSION>=0x02020000 then
print("Warning: Using libevent version 2.2.x is not supported, please use 2.1.x, otherwise you may encounter issues.") print("Warning: Using libevent version 2.2.x is not supported, please use 2.1.x, otherwise you may encounter issues.")
end end
if EVENT_VERSION>=0x02010000 and WINXP_SUPPORT then if EVENT_VERSION>=0x02010000 and WINXP_SUPPORT then
print("Warning: libevent 2.1 uses some new APIs which require Windows Vista or later, so WinXP support will be not valid.") print("Warning: libevent 2.1 uses some new APIs which require Windows Vista or later, so WinXP support will be invalid.")
end end
includedirs { "include", "compat" } includedirs { "include", "compat" }
......
...@@ -157,7 +157,7 @@ if GetParam("no-dxsdk") then ...@@ -157,7 +157,7 @@ if GetParam("no-dxsdk") then
end end
if USE_DXSDK and os.istarget("windows") then if USE_DXSDK and os.istarget("windows") then
if not os.getenv("DXSDK_DIR") then if not os.getenv("DXSDK_DIR") then
print("DXSDK_DIR environment variable not set, it seems you don't have the DirectX SDK installed. DirectX mode will be disabled.") print("Warning: DXSDK_DIR environment variable not set, it seems you don't have the DirectX SDK installed. DirectX mode will be disabled.")
USE_DXSDK = false USE_DXSDK = false
end end
end end
......
1 ICON "ygopro.ico" 1 ICON "ygopro.ico"
1 VERSIONINFO 1 VERSIONINFO
FILEVERSION 1, 0, 36, 1 FILEVERSION 1, 0, 36, 2
PRODUCTVERSION 1, 0, 36, 1 PRODUCTVERSION 1, 0, 36, 2
FILEOS 0x4 FILEOS 0x4
FILETYPE 0x1 FILETYPE 0x1
...@@ -16,8 +16,8 @@ VALUE "InternalName", "YGOPro" ...@@ -16,8 +16,8 @@ VALUE "InternalName", "YGOPro"
VALUE "LegalCopyright", "Copyright (C) 2025 Fluorohydride" VALUE "LegalCopyright", "Copyright (C) 2025 Fluorohydride"
VALUE "OriginalFilename", "YGOPro.exe" VALUE "OriginalFilename", "YGOPro.exe"
VALUE "ProductName", "YGOPro" VALUE "ProductName", "YGOPro"
VALUE "FileVersion", "1.036.1" VALUE "FileVersion", "1.036.2"
VALUE "ProductVersion", "1.036.1" VALUE "ProductVersion", "1.036.2"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
......
Subproject commit a76cc0be83a3928a726547a239bcca8013ce3225 Subproject commit cfbb14cdbf7b2095db543f2620eb2e88b0fb9220
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