Commit 1cd16fb5 authored by mercury233's avatar mercury233

Merge branch 'fh' into patch-premake-freetype

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