Commit 3e1186a9 authored by wind2009's avatar wind2009

Merge branch 'server' of https://github.com/purerosefallen/ygopro into 2pick

parents cb3585cc e6005fa5
...@@ -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: |
...@@ -437,8 +437,8 @@ jobs: ...@@ -437,8 +437,8 @@ jobs:
- name: Copy premake files - name: Copy premake files
run: | run: |
cp -r premake/* . cp -pr premake/* .
cp -r resource/* . cp -pr resource/* .
- name: Use premake to generate make files (apt packages) - name: Use premake to generate make files (apt packages)
if: matrix.static-link != true if: matrix.static-link != true
...@@ -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: |
...@@ -664,8 +664,8 @@ jobs: ...@@ -664,8 +664,8 @@ jobs:
- name: Copy premake files - name: Copy premake files
run: | run: |
cp -r premake/* . cp -pr premake/* .
cp -r resource/* . cp -pr resource/* .
- name: Use premake to generate make files (Homebrew packages) - name: Use premake to generate make files (Homebrew packages)
if: matrix.static-link != true if: matrix.static-link != true
...@@ -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: |
......
...@@ -93,8 +93,9 @@ mat_windows: ...@@ -93,8 +93,9 @@ mat_windows:
._exec_build: ._exec_build:
stage: build stage: build
#variables: variables:
# NO_LUA_SAFE: '1' # on client no lua safe # NO_LUA_SAFE: '1' # on client no lua safe
GIT_STRATEGY: clone
#cache: #cache:
# key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG" # key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
# paths: # paths:
...@@ -124,6 +125,15 @@ exec_windows: ...@@ -124,6 +125,15 @@ exec_windows:
- mkdir dist\windows - mkdir dist\windows
- copy bin\release\x64\ygopro.exe dist\windows\ygopro.exe - copy bin\release\x64\ygopro.exe dist\windows\ygopro.exe
exec_windows_pro2:
extends: .exec_windows
script:
- '.\premake5.exe vs2019 --server-pro2-support'
- cmd /c '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\msbuild.exe" build\YGOPro.sln /m /p:Configuration=Release /p:Platform=x64'
- mkdir dist
- mkdir dist\windows
- copy bin\release\x64\AI.Server.exe dist\windows\AI.Server.exe
exec_windows_pro3: exec_windows_pro3:
extends: .exec_windows extends: .exec_windows
script: script:
...@@ -133,12 +143,24 @@ exec_windows_pro3: ...@@ -133,12 +143,24 @@ exec_windows_pro3:
- mkdir dist\windows - mkdir dist\windows
- copy bin\release\x64\ygoserver.dll dist\windows\ygoserver.dll - copy bin\release\x64\ygoserver.dll dist\windows\ygoserver.dll
exec_windows_mdpro2:
extends: .exec_windows
script:
- '.\premake5.exe vs2019 --server-pro3-support --log-in-chat --server-pro2-support'
- cmd /c '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\msbuild.exe" build\YGOPro.sln /m /p:Configuration=Release /p:Platform=x64'
- mkdir dist
- mkdir dist\windows
- copy bin\release\x64\ygoserver.dll dist\windows\ygoserver-mdpro2.dll
.exec_unix_common: .exec_unix_common:
extends: ._exec_build extends: ._exec_build
variables: variables:
RELEASE_DIR: '' RELEASE_DIR: ''
TARGET_FILE: ygopro TARGET_FILE: ygopro
PREMAKE5_BIN: premake5 PREMAKE5_BIN: premake5
BUILD_EVENT: '1'
BUILD_IRRLICHT: '1'
BUILD_SQLITE: '1'
script: script:
- ./.ci/configure-libevent.sh - ./.ci/configure-libevent.sh
- $PREMAKE5_BIN gmake - $PREMAKE5_BIN gmake
...@@ -318,6 +340,8 @@ upload_to_minio: ...@@ -318,6 +340,8 @@ upload_to_minio:
- exec_linux - exec_linux
- exec_linuxarm - exec_linuxarm
- exec_windows_pro3 - exec_windows_pro3
- exec_windows_pro2
- exec_windows_mdpro2
- exec_linux_pro3 - exec_linux_pro3
- exec_linuxarm_pro3 - exec_linuxarm_pro3
- exec_debian - exec_debian
......
No preview for this file type
...@@ -2,37 +2,52 @@ ...@@ -2,37 +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;
} }
static unsigned int ReadUInt32(unsigned char*& p) { template<typename T>
return buffer_read<uint32_t>(p); static void Write(unsigned char*& p, T value) {
std::memcpy(p, &value, sizeof(T));
p += sizeof(T);
} }
static short ReadInt16(unsigned char*& p) {
return buffer_read<int16_t>(p); // for compatibility
[[deprecated]]
static int32_t ReadInt32(unsigned char*& p) {
return Read<int32_t>(p);
} }
static unsigned short ReadUInt16(unsigned char*& p) { [[deprecated]]
return buffer_read<uint16_t>(p); static short ReadInt16(unsigned char*& 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.
...@@ -67,64 +82,18 @@ public: ...@@ -67,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);
...@@ -143,111 +112,31 @@ public: ...@@ -143,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]) {
...@@ -273,7 +162,6 @@ public: ...@@ -273,7 +162,6 @@ public:
} }
else else
return 0; return 0;
} }
}; };
......
...@@ -35,27 +35,27 @@ void ClientCard::SetCode(unsigned int x) { ...@@ -35,27 +35,27 @@ void ClientCard::SetCode(unsigned int x) {
if((location == LOCATION_HAND) && (code != x)) { if((location == LOCATION_HAND) && (code != x)) {
code = x; code = x;
mainGame->dField.MoveCard(this, 5); mainGame->dField.MoveCard(this, 5);
} else } else {
if (x == 0 && code != 0) {
chain_code = code;
}
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)) { SetCode(pdata);
code = pdata;
mainGame->dField.MoveCard(this, 5);
} else
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;
} }
......
...@@ -27,13 +27,11 @@ ClientField::~ClientField() { ...@@ -27,13 +27,11 @@ ClientField::~ClientField() {
} }
hand[i].clear(); hand[i].clear();
for (auto& card : mzone[i]) { for (auto& card : mzone[i]) {
if (card) delete card;
delete card;
card = nullptr; card = nullptr;
} }
for (auto& card : szone[i]) { for (auto& card : szone[i]) {
if (card) delete card;
delete card;
card = nullptr; card = nullptr;
} }
for (auto& card : grave[i]) { for (auto& card : grave[i]) {
...@@ -44,7 +42,6 @@ ClientField::~ClientField() { ...@@ -44,7 +42,6 @@ ClientField::~ClientField() {
delete card; delete card;
} }
remove[i].clear(); remove[i].clear();
for (auto& card : extra[i]) { for (auto& card : extra[i]) {
delete card; delete card;
} }
...@@ -57,30 +54,33 @@ ClientField::~ClientField() { ...@@ -57,30 +54,33 @@ ClientField::~ClientField() {
} }
void ClientField::Clear() { void ClientField::Clear() {
for(int i = 0; i < 2; ++i) { for(int i = 0; i < 2; ++i) {
for(auto cit = deck[i].begin(); cit != deck[i].end(); ++cit) for (auto& card : deck[i]) {
delete *cit; delete card;
}
deck[i].clear(); deck[i].clear();
for(auto cit = hand[i].begin(); cit != hand[i].end(); ++cit) for (auto& card : hand[i]) {
delete *cit; delete card;
}
hand[i].clear(); hand[i].clear();
for(auto cit = mzone[i].begin(); cit != mzone[i].end(); ++cit) { for (auto& card : mzone[i]) {
if(*cit) delete card;
delete *cit; card = nullptr;
*cit = 0; }
} for (auto& card : szone[i]) {
for(auto cit = szone[i].begin(); cit != szone[i].end(); ++cit) { delete card;
if(*cit) card = nullptr;
delete *cit; }
*cit = 0; for (auto& card : grave[i]) {
} delete card;
for(auto cit = grave[i].begin(); cit != grave[i].end(); ++cit) }
delete *cit;
grave[i].clear(); grave[i].clear();
for(auto cit = remove[i].begin(); cit != remove[i].end(); ++cit) for (auto& card : remove[i]) {
delete *cit; delete card;
}
remove[i].clear(); remove[i].clear();
for(auto cit = extra[i].begin(); cit != extra[i].end(); ++cit) for (auto& card : extra[i]) {
delete *cit; delete card;
}
extra[i].clear(); extra[i].clear();
deck_act[i] = false; deck_act[i] = false;
grave_act[i] = false; grave_act[i] = false;
...@@ -88,11 +88,13 @@ void ClientField::Clear() { ...@@ -88,11 +88,13 @@ void ClientField::Clear() {
extra_act[i] = false; extra_act[i] = false;
pzone_act[i] = false; pzone_act[i] = false;
} }
for(auto cit = limbo_temp.begin(); cit != limbo_temp.end(); ++cit) for (auto& card : limbo_temp) {
delete *cit; delete card;
}
limbo_temp.clear(); limbo_temp.clear();
for(auto sit = overlay_cards.begin(); sit != overlay_cards.end(); ++sit) for (auto& card : overlay_cards) {
delete *sit; delete card;
}
overlay_cards.clear(); overlay_cards.clear();
extra_p_count[0] = 0; extra_p_count[0] = 0;
extra_p_count[1] = 0; extra_p_count[1] = 0;
...@@ -325,7 +327,7 @@ ClientCard* ClientField::RemoveCard(int controler, int location, int sequence) { ...@@ -325,7 +327,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);
RefreshCardCountDisplay(); RefreshCardCountDisplay();
...@@ -359,7 +361,7 @@ void ClientField::UpdateFieldCard(int controler, int location, unsigned char* da ...@@ -359,7 +361,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;
...@@ -427,7 +429,8 @@ void ClientField::ClearChainSelect() { ...@@ -427,7 +429,8 @@ void ClientField::ClearChainSelect() {
conti_act = false; conti_act = false;
} }
// needs to be synchronized with EGET_SCROLL_BAR_CHANGED // needs to be synchronized with EGET_SCROLL_BAR_CHANGED
void ClientField::ShowSelectCard(bool buttonok, bool chain) { void ClientField::ShowSelectCard(bool buttonok, bool is_continuous) {
select_continuous = is_continuous;
if(cant_check_grave) { if(cant_check_grave) {
bool has_card_in_grave = false; bool has_card_in_grave = false;
for (auto& pcard : selectable_cards) { for (auto& pcard : selectable_cards) {
...@@ -454,7 +457,7 @@ void ClientField::ShowSelectCard(bool buttonok, bool chain) { ...@@ -454,7 +457,7 @@ void ClientField::ShowSelectCard(bool buttonok, bool chain) {
// image // image
if(selectable_cards[i]->code) if(selectable_cards[i]->code)
mainGame->imageLoading.insert(std::make_pair(mainGame->btnCardSelect[i], selectable_cards[i]->code)); mainGame->imageLoading.insert(std::make_pair(mainGame->btnCardSelect[i], selectable_cards[i]->code));
else if(conti_selecting) else if(select_continuous)
mainGame->imageLoading.insert(std::make_pair(mainGame->btnCardSelect[i], selectable_cards[i]->chain_code)); mainGame->imageLoading.insert(std::make_pair(mainGame->btnCardSelect[i], selectable_cards[i]->chain_code));
else else
mainGame->btnCardSelect[i]->setImage(imageManager.tCover[selectable_cards[i]->controler + 2]); mainGame->btnCardSelect[i]->setImage(imageManager.tCover[selectable_cards[i]->controler + 2]);
...@@ -464,8 +467,8 @@ void ClientField::ShowSelectCard(bool buttonok, bool chain) { ...@@ -464,8 +467,8 @@ void ClientField::ShowSelectCard(bool buttonok, bool chain) {
if(mainGame->dInfo.curMsg != MSG_SORT_CARD) { if(mainGame->dInfo.curMsg != MSG_SORT_CARD) {
// text // text
wchar_t formatBuffer[2048]; wchar_t formatBuffer[2048];
if(conti_selecting) if(select_continuous)
myswprintf(formatBuffer, L"%ls", DataManager::unknown_string); myswprintf(formatBuffer, L"%ls", dataManager.unknown_string);
else if(cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE) else if(cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE)
myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0)); myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0));
else if(selectable_cards[i]->location == LOCATION_OVERLAY) else if(selectable_cards[i]->location == LOCATION_OVERLAY)
...@@ -482,7 +485,7 @@ void ClientField::ShowSelectCard(bool buttonok, bool chain) { ...@@ -482,7 +485,7 @@ void ClientField::ShowSelectCard(bool buttonok, bool chain) {
if (selectable_cards[i]->is_selected) if (selectable_cards[i]->is_selected)
mainGame->stCardPos[i]->setBackgroundColor(0xffffff00); mainGame->stCardPos[i]->setBackgroundColor(0xffffff00);
else { else {
if(conti_selecting) if(select_continuous)
mainGame->stCardPos[i]->setBackgroundColor(0xffffffff); mainGame->stCardPos[i]->setBackgroundColor(0xffffffff);
else if(selectable_cards[i]->location == LOCATION_OVERLAY) { else if(selectable_cards[i]->location == LOCATION_OVERLAY) {
if(selectable_cards[i]->owner != selectable_cards[i]->overlayTarget->controler) if(selectable_cards[i]->owner != selectable_cards[i]->overlayTarget->controler)
...@@ -1424,7 +1427,8 @@ bool ClientField::check_sum_trib(std::set<ClientCard*>::const_iterator index, st ...@@ -1424,7 +1427,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) {
...@@ -1514,9 +1518,15 @@ static bool is_declarable(const CardData& cd, const std::vector<unsigned int>& o ...@@ -1514,9 +1518,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;
...@@ -1560,12 +1570,13 @@ static bool is_declarable(const CardData& cd, const std::vector<unsigned int>& o ...@@ -1560,12 +1570,13 @@ 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& _strings = dataManager.GetStringTable();
auto it = _strings.find(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;
} }
...@@ -1574,27 +1585,32 @@ void ClientField::UpdateDeclarableList() { ...@@ -1574,27 +1585,32 @@ void ClientField::UpdateDeclarableList() {
if(pname[0] == 0 && mainGame->dInfo.announce_cache.size()) { if(pname[0] == 0 && mainGame->dInfo.announce_cache.size()) {
for(int i = 0; i < mainGame->dInfo.announce_cache.size(); ++i) { for(int i = 0; i < mainGame->dInfo.announce_cache.size(); ++i) {
unsigned int cache_code = mainGame->dInfo.announce_cache[i]; unsigned int cache_code = mainGame->dInfo.announce_cache[i];
if(dataManager.GetString(cache_code, &cstr) && dataManager.GetData(cache_code, &cd) && is_declarable(cd, declare_opcodes)) { if(dataManager.GetData(cache_code, &cd) && is_declarable(cd, declare_opcodes)) {
mainGame->lstANCard->addItem(cstr.name.c_str()); auto it = dataManager.GetStringPointer(cache_code);
mainGame->lstANCard->addItem(it->second.name.c_str());
ancard.push_back(cache_code); ancard.push_back(cache_code);
} }
} }
// if(ancard.size()) // if(ancard.size())
// return; // return;
} }
for(auto cit = dataManager.strings_begin(); cit != dataManager.strings_end(); ++cit) { auto& _datas = dataManager.GetDataTable();
if(cit->second.name.find(pname) != std::wstring::npos || mainGame->CheckRegEx(cit->second.name, pname)) { auto& _strings = dataManager.GetStringTable();
auto cp = dataManager.GetCodePointer(cit->first); for(auto& entry : _strings) {
if (cp == dataManager.datas_end()) auto& code = entry.first;
auto& str = entry.second;
if(str.name.find(pname) != std::wstring::npos) {
auto cp = _datas.find(code);
if (cp == _datas.end())
continue; continue;
//datas.alias can be double card names or alias //datas.alias can be double card names or alias
if(is_declarable(cp->second, declare_opcodes)) { if(is_declarable(cp->second, declare_opcodes)) {
if(pname == cit->second.name) { //exact match if(pname == str.name) { //exact match
mainGame->lstANCard->insertItem(0, cit->second.name.c_str(), -1); mainGame->lstANCard->insertItem(0, str.name.c_str(), -1);
ancard.insert(ancard.begin(), cit->first); ancard.insert(ancard.begin(), code);
} else { } else {
mainGame->lstANCard->addItem(cit->second.name.c_str()); mainGame->lstANCard->addItem(str.name.c_str());
ancard.push_back(cit->first); ancard.push_back(code);
} }
} }
} }
......
...@@ -88,14 +88,14 @@ public: ...@@ -88,14 +88,14 @@ public:
ChainInfo current_chain; ChainInfo current_chain;
bool last_chain{ false }; bool last_chain{ false };
bool deck_reversed{ false }; bool deck_reversed{ false };
bool conti_selecting{ false }; bool select_continuous{ false };
bool cant_check_grave{ false }; bool cant_check_grave{ false };
bool tag_surrender{ false }; bool tag_surrender{ false };
bool tag_teammate_surrender{ false }; bool tag_teammate_surrender{ false };
std::mt19937 rnd; std::mt19937 rnd;
ClientField(); ClientField();
~ClientField(); ~ClientField() override;
void Clear(); void Clear();
void Initial(int player, int deckc, int extrac, int sidec = 0); void Initial(int player, int deckc, int extrac, int sidec = 0);
void ResetSequence(std::vector<ClientCard*>& list, bool reset_height); void ResetSequence(std::vector<ClientCard*>& list, bool reset_height);
...@@ -107,7 +107,7 @@ public: ...@@ -107,7 +107,7 @@ public:
void ClearCommandFlag(); void ClearCommandFlag();
void ClearSelect(); void ClearSelect();
void ClearChainSelect(); void ClearChainSelect();
void ShowSelectCard(bool buttonok = false, bool chain = false); void ShowSelectCard(bool buttonok = false, bool is_continuous = false);
void ShowChainCard(); void ShowChainCard();
void ShowLocationCard(); void ShowLocationCard();
void ShowSelectOption(int select_hint = 0); void ShowSelectOption(int select_hint = 0);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#define IRR_COMPILE_WITH_DX9_DEV_PACK #define IRR_COMPILE_WITH_DX9_DEV_PACK
#include <cerrno> #include <cerrno>
#include <vector>
#ifdef _WIN32 #ifdef _WIN32
...@@ -13,7 +14,7 @@ ...@@ -13,7 +14,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
...@@ -72,8 +73,12 @@ extern char** environ; ...@@ -72,8 +73,12 @@ extern char** environ;
#include "../ocgcore/ocgapi.h" #include "../ocgcore/ocgapi.h"
template<size_t N, typename... TR> template<size_t N, typename... TR>
inline int myswprintf(wchar_t(&buf)[N], const wchar_t* fmt, TR... args) { inline int myswprintf(wchar_t(&buf)[N], const wchar_t* fmt, TR&&... args) {
return std::swprintf(buf, N, fmt, args...); return std::swprintf(buf, N, fmt, std::forward<TR>(args)...);
}
template<size_t N, typename... TR>
inline int mysnprintf(char(&buf)[N], const char* fmt, TR&&... args) {
return std::snprintf(buf, N, fmt, std::forward<TR>(args)...);
} }
inline FILE* mywfopen(const wchar_t* filename, const char* mode) { inline FILE* mywfopen(const wchar_t* filename, const char* mode) {
...@@ -90,20 +95,7 @@ inline FILE* mywfopen(const wchar_t* filename, const char* mode) { ...@@ -90,20 +95,7 @@ inline FILE* mywfopen(const wchar_t* filename, const char* mode) {
return fp; return fp;
} }
#if !defined(_WIN32)
#define myfopen std::fopen #define myfopen std::fopen
#elif defined(WDK_NTDDI_VERSION) && (WDK_NTDDI_VERSION >= 0x0A000005) // Redstone 4, Version 1803, Build 17134.
#define FOPEN_WINDOWS_SUPPORT_UTF8
#define myfopen std::fopen
#else
inline FILE* myfopen(const char* filename, const char* mode) {
wchar_t wfilename[256]{};
BufferIO::DecodeUTF8(filename, wfilename);
wchar_t wmode[20]{};
BufferIO::CopyCharArray(mode, wmode);
return _wfopen(wfilename, wmode);
}
#endif
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT) #if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
#include <irrlicht.h> #include <irrlicht.h>
...@@ -116,7 +108,7 @@ extern bool auto_watch_mode; ...@@ -116,7 +108,7 @@ extern bool auto_watch_mode;
extern bool open_file; extern bool open_file;
extern wchar_t open_file_name[256]; extern wchar_t open_file_name[256];
extern bool bot_mode; extern bool bot_mode;
extern bool expansions_specified;
extern std::vector<std::wstring> expansions_list; extern std::vector<std::wstring> expansions_list;
extern std::vector<std::wstring> extra_script_list;
#endif #endif
This diff is collapsed.
...@@ -15,19 +15,36 @@ namespace irr { ...@@ -15,19 +15,36 @@ 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 +54,8 @@ struct CardString { ...@@ -37,8 +54,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:
...@@ -66,20 +83,24 @@ public: ...@@ -66,20 +83,24 @@ public:
#endif #endif
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;
#ifndef YGOPRO_SERVER_MODE
string_pointer GetStringPointer(uint32_t code) const;
#endif
const std::unordered_map<uint32_t, CardDataC>& GetDataTable() const {
return _datas;
}
#ifndef YGOPRO_SERVER_MODE #ifndef YGOPRO_SERVER_MODE
string_pointer GetStringPointer(unsigned int code) const; const std::unordered_map<uint32_t, CardString>& GetStringTable() const {
code_pointer datas_begin() const; return _strings;
code_pointer datas_end() const; }
string_pointer strings_begin() const;
string_pointer strings_end() const;
#endif #endif
bool GetData(unsigned int code, CardData* pData) const; bool GetData(uint32_t code, CardData* pData) const;
#ifndef YGOPRO_SERVER_MODE #ifndef YGOPRO_SERVER_MODE
bool GetString(unsigned int code, CardString* pStr) const; bool GetString(uint32_t code, CardString* pStr) const;
const wchar_t* GetName(unsigned int code) const; const wchar_t* GetName(uint32_t code) const;
const wchar_t* GetText(unsigned int code) const; const wchar_t* GetText(uint32_t code) const;
const wchar_t* GetDesc(unsigned int strCode) 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;
...@@ -99,13 +120,22 @@ public: ...@@ -99,13 +120,22 @@ public:
std::unordered_map<unsigned int, std::wstring> _sysStrings; std::unordered_map<unsigned int, std::wstring> _sysStrings;
std::vector<std::pair<std::wstring, std::wstring>> _serverStrings; std::vector<std::pair<std::wstring, std::wstring>> _serverStrings;
#endif #endif
const wchar_t* unknown_string{ L"???" };
char errmsg[512]{}; char errmsg[512]{};
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
irr::io::IFileSystem* FileSystem{};
#endif
static constexpr int STRING_ID_ATTRIBUTE = 1010;
static constexpr int STRING_ID_RACE = 1020;
static constexpr int STRING_ID_TYPE = 1050;
static constexpr int TYPES_COUNT = 27;
static unsigned char scriptBuffer[0x100000]; static unsigned char scriptBuffer[0x100000];
static const wchar_t* unknown_string;
static uint32_t CardReader(uint32_t, card_data*); static uint32_t CardReader(uint32_t, card_data*);
static unsigned char* ScriptReaderEx(const char* script_name, int* slen); static unsigned char* ScriptReaderEx(const char* script_name, int* slen);
static unsigned char* ScriptReaderExSingle(const char* path, const char* script_name, int* slen, int pre_len = 2, unsigned int use_irr = FALSE); static unsigned char* ScriptReaderExSingle(const char* path, const char* script_name, int* slen, int pre_len = 2, unsigned int use_irr = FALSE);
void LoadExtraScripts(intptr_t pduel);
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT) #if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
//read by IFileSystem //read by IFileSystem
...@@ -113,10 +143,6 @@ public: ...@@ -113,10 +143,6 @@ public:
#endif #endif
//read by fread //read by fread
static unsigned char* ReadScriptFromFile(const char* script_name, int* slen); static unsigned char* ReadScriptFromFile(const char* script_name, int* slen);
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
static irr::io::IFileSystem* FileSystem;
#endif
#ifndef YGOPRO_SERVER_MODE #ifndef YGOPRO_SERVER_MODE
static bool deck_sort_lv(code_pointer l1, code_pointer l2); static bool deck_sort_lv(code_pointer l1, code_pointer l2);
...@@ -131,9 +157,9 @@ public: ...@@ -131,9 +157,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;
std::wstring iniName; std::wstring iniName;
std::wstring iniHost; std::wstring iniHost;
std::wstring iniPort; std::wstring iniPort;
......
This diff is collapsed.
This diff is collapsed.
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <sstream> #include <sstream>
#include <functional>
#include "data_manager.h" #include "data_manager.h"
#include "bufferio.h" #include "bufferio.h"
...@@ -24,16 +25,28 @@ ...@@ -24,16 +25,28 @@
#endif #endif
namespace ygo { namespace ygo {
constexpr int DECK_MAX_SIZE = YGOPRO_MAX_DECK;
constexpr int DECK_MIN_SIZE = YGOPRO_MIN_DECK; constexpr int DECK_MAX_SIZE = YGOPRO_MAX_DECK;
constexpr int EXTRA_MAX_SIZE = YGOPRO_MAX_EXTRA; constexpr int DECK_MIN_SIZE = YGOPRO_MIN_DECK;
constexpr int SIDE_MAX_SIZE = YGOPRO_MAX_SIDE; constexpr int EXTRA_MAX_SIZE = YGOPRO_MAX_EXTRA;
constexpr int PACK_MAX_SIZE = 1000; constexpr int SIDE_MAX_SIZE = YGOPRO_MAX_SIDE;
constexpr int PACK_MAX_SIZE = 1000;
constexpr int MAINC_MAX = 250; // the limit of card_state
constexpr int SIDEC_MAX = MAINC_MAX;
constexpr int DECK_CATEGORY_PACK = 0;
constexpr int DECK_CATEGORY_BOT = 1;
constexpr int DECK_CATEGORY_NONE = 2;
constexpr int DECK_CATEGORY_SEPARATOR = 3;
constexpr int DECK_CATEGORY_CUSTOM = 4;
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;
std::unordered_map<std::wstring, uint32_t> credit_limits;
std::unordered_map<uint32_t, std::unordered_map<std::wstring, uint32_t>> credits;
}; };
struct Deck { struct Deck {
std::vector<code_pointer> main; std::vector<code_pointer> main;
...@@ -60,11 +73,13 @@ struct DeckArray { ...@@ -60,11 +73,13 @@ struct DeckArray {
class DeckManager { class DeckManager {
public: public:
#ifndef YGOPRO_SERVER_MODE
Deck current_deck; Deck current_deck;
#endif
std::vector<LFList> _lfList; std::vector<LFList> _lfList;
#ifndef YGOPRO_SERVER_MODE #ifndef YGOPRO_SERVER_MODE
static char deckBuffer[0x10000]; static constexpr int MAX_YDK_SIZE = 0x10000;
#endif #endif
void LoadLFListSingle(const char* path, bool insert = false); void LoadLFListSingle(const char* path, bool insert = false);
...@@ -104,47 +119,7 @@ public: ...@@ -104,47 +119,7 @@ public:
#endif //YGOPRO_SERVER_MODE #endif //YGOPRO_SERVER_MODE
private: private:
template<typename LineProvider> void LoadLFListFromLineProvider(const std::function<bool(char*, size_t)>& getLine, bool insert = false);
void _LoadLFListFromLineProvider(LineProvider getLine, bool insert = false) {
std::vector<LFList> loadedLists;
auto cur = loadedLists.rend(); // 注意:在临时 list 上操作
char line[256]{};
wchar_t strBuffer[256]{};
char str1[16]{};
while (getLine(line, sizeof(line))) {
if (line[0] == '#')
continue;
if (line[0] == '!') {
auto len = std::strcspn(line, "\r\n");
line[len] = 0;
BufferIO::DecodeUTF8(&line[1], strBuffer);
LFList newlist;
newlist.listName = strBuffer;
newlist.hash = 0x7dfcee6a;
loadedLists.push_back(newlist);
cur = loadedLists.rbegin();
continue;
}
if (cur == loadedLists.rend())
continue;
unsigned int code = 0;
int count = -1;
if (std::sscanf(line, "%10s%*[ ]%1d", str1, &count) != 2)
continue;
if (count < 0 || count > 2)
continue;
code = std::strtoul(str1, nullptr, 10);
cur->content[code] = count;
cur->hash = cur->hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + count)) | (code >> (5 - count)));
}
if (insert) {
_lfList.insert(_lfList.begin(), loadedLists.begin(), loadedLists.end());
} else {
_lfList.insert(_lfList.end(), loadedLists.begin(), loadedLists.end());
}
}
}; };
extern DeckManager deckManager; extern DeckManager deckManager;
......
...@@ -371,6 +371,7 @@ void Game::DrawCard(ClientCard* pcard) { ...@@ -371,6 +371,7 @@ void Game::DrawCard(ClientCard* pcard) {
if(pcard->aniFrame == 0) { if(pcard->aniFrame == 0) {
pcard->is_moving = false; pcard->is_moving = false;
pcard->is_fading = false; pcard->is_fading = false;
pcard->chain_code = 0;
} }
} }
matManager.mCard.AmbientColor = 0xffffffff; matManager.mCard.AmbientColor = 0xffffffff;
...@@ -378,7 +379,10 @@ void Game::DrawCard(ClientCard* pcard) { ...@@ -378,7 +379,10 @@ void Game::DrawCard(ClientCard* pcard) {
driver->setTransform(irr::video::ETS_WORLD, pcard->mTransform); driver->setTransform(irr::video::ETS_WORLD, pcard->mTransform);
auto m22 = pcard->mTransform(2, 2); auto m22 = pcard->mTransform(2, 2);
if(m22 > -0.99 || pcard->is_moving) { if(m22 > -0.99 || pcard->is_moving) {
matManager.mCard.setTexture(0, imageManager.GetTexture(pcard->code)); auto code = pcard->code;
if (code == 0 && pcard->is_moving)
code = pcard->chain_code;
matManager.mCard.setTexture(0, imageManager.GetTexture(code));
driver->setMaterial(matManager.mCard); driver->setMaterial(matManager.mCard);
driver->drawVertexPrimitiveList(matManager.vCardFront, 4, matManager.iRectangle, 2); driver->drawVertexPrimitiveList(matManager.vCardFront, 4, matManager.iRectangle, 2);
} }
...@@ -1167,7 +1171,6 @@ void Game::HideElement(irr::gui::IGUIElement * win, bool set_action) { ...@@ -1167,7 +1171,6 @@ void Game::HideElement(irr::gui::IGUIElement * win, bool set_action) {
if(win == wCardSelect) { if(win == wCardSelect) {
for(int i = 0; i < 5; ++i) for(int i = 0; i < 5; ++i)
btnCardSelect[i]->setDrawImage(false); btnCardSelect[i]->setDrawImage(false);
dField.conti_selecting = false;
stCardListTip->setVisible(false); stCardListTip->setVisible(false);
for(auto& pcard : dField.selectable_cards) for(auto& pcard : dField.selectable_cards)
dField.SetShowMark(pcard, false); dField.SetShowMark(pcard, false);
...@@ -1197,7 +1200,7 @@ void Game::WaitFrameSignal(int frame) { ...@@ -1197,7 +1200,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;
...@@ -1214,18 +1217,42 @@ void Game::DrawThumb(code_pointer cp, irr::core::vector2di pos, const LFList* lf ...@@ -1214,18 +1217,42 @@ void Game::DrawThumb(code_pointer cp, irr::core::vector2di pos, const LFList* lf
otloc = irr::core::recti(pos.X + 7, pos.Y + 50 * mainGame->yScale, pos.X + 37 * mainGame->xScale, pos.Y + 65 * mainGame->yScale); otloc = irr::core::recti(pos.X + 7, pos.Y + 50 * mainGame->yScale, pos.X + 37 * mainGame->xScale, pos.Y + 65 * mainGame->yScale);
} }
driver->draw2DImage(img, dragloc, irr::core::rect<irr::s32>(0, 0, size.Width, size.Height)); driver->draw2DImage(img, dragloc, irr::core::rect<irr::s32>(0, 0, size.Width, size.Height));
auto current_limitloc = limitloc;
auto credit_max_display = CARD_THUMB_WIDTH / 20;
auto next_limitloc = [&]() {
auto this_limitloc = current_limitloc;
auto width = current_limitloc.getWidth();
current_limitloc.UpperLeftCorner.X += width;
current_limitloc.LowerRightCorner.X += width;
--credit_max_display;
return this_limitloc;
};
auto lfit = lflist->content.find(lcode); auto lfit = lflist->content.find(lcode);
if (lfit != lflist->content.end()) { if (lfit != lflist->content.end() && lfit->second >= 0 && lfit->second <= 2) {
switch(lfit->second) { auto lim_texture_offset_x = 0;
case 0: auto lim_texture_offset_y = 0;
driver->draw2DImage(imageManager.tLim, limitloc, irr::core::recti(0, 0, 64, 64), 0, 0, true); if(lfit->second == 1) {
break; lim_texture_offset_x = 64;
case 1: } else if(lfit->second == 2) {
driver->draw2DImage(imageManager.tLim, limitloc, irr::core::recti(64, 0, 128, 64), 0, 0, true); lim_texture_offset_y = 64;
break; }
case 2: driver->draw2DImage(imageManager.tLim, next_limitloc(), irr::core::recti(lim_texture_offset_x, lim_texture_offset_y, lim_texture_offset_x + 64, lim_texture_offset_y + 64), 0, 0, true);
driver->draw2DImage(imageManager.tLim, limitloc, irr::core::recti(0, 64, 64, 128), 0, 0, true); }
break; auto lfcredit = lflist->credits.find(lcode);
if(lfcredit != lflist->credits.end()) {
for(auto& credit_entry : lfcredit->second) {
if(credit_max_display <= 0)
break;
auto value = credit_entry.second;
if(value > 0 && value <= 100) {
auto cvalue = value - 1; // 1-100 => 0-99
// pick the first and second digit
auto digit1 = cvalue / 10;
auto digit2 = cvalue % 10;
auto credit_texture_offset_x = digit2 * 64;
auto credit_texture_offset_y = digit1 * 64;
driver->draw2DImage(imageManager.tLimCredit, next_limitloc(), irr::core::recti(credit_texture_offset_x, credit_texture_offset_y, credit_texture_offset_x + 64, credit_texture_offset_y + 64), 0, 0, true);
}
} }
} }
bool showAvail = false; bool showAvail = false;
...@@ -1434,8 +1461,9 @@ void Game::DrawDeckBd() { ...@@ -1434,8 +1461,9 @@ void Game::DrawDeckBd() {
else else
myswprintf(adBuffer, L"%d/-", ptr->second.attack); myswprintf(adBuffer, L"%d/-", ptr->second.attack);
} }
myswprintf(textBuffer, L"%ls/%ls %ls%d", dataManager.FormatAttribute(ptr->second.attribute).c_str(), dataManager.FormatRace(ptr->second.race).c_str(), const auto& attribute = dataManager.FormatAttribute(ptr->second.attribute);
form, ptr->second.level); const auto& race = dataManager.FormatRace(ptr->second.race);
myswprintf(textBuffer, L"%ls/%ls %ls%d", attribute.c_str(), race.c_str(), form, ptr->second.level);
DrawShadowText(textFont, textBuffer, Resize(860, 187 + i * 66, 955, 207 + i * 66), Resize(1, 1, 0, 0)); DrawShadowText(textFont, textBuffer, Resize(860, 187 + i * 66, 955, 207 + i * 66), Resize(1, 1, 0, 0));
if(ptr->second.type & TYPE_PENDULUM) { if(ptr->second.type & TYPE_PENDULUM) {
myswprintf(scaleBuffer, L" %d/%d", ptr->second.lscale, ptr->second.rscale); myswprintf(scaleBuffer, L" %d/%d", ptr->second.lscale, ptr->second.rscale);
...@@ -1445,7 +1473,8 @@ void Game::DrawDeckBd() { ...@@ -1445,7 +1473,8 @@ void Game::DrawDeckBd() {
} else { } else {
myswprintf(textBuffer, L"%ls", dataManager.GetName(ptr->first)); myswprintf(textBuffer, L"%ls", dataManager.GetName(ptr->first));
DrawShadowText(textFont, textBuffer, Resize(860, 165 + i * 66, 955, 185 + i * 66), Resize(1, 1, 0, 0)); DrawShadowText(textFont, textBuffer, Resize(860, 165 + i * 66, 955, 185 + i * 66), Resize(1, 1, 0, 0));
myswprintf(textBuffer, L"%ls", dataManager.FormatType(ptr->second.type).c_str()); const auto& type = dataManager.FormatType(ptr->second.type);
myswprintf(textBuffer, L"%ls", type.c_str());
DrawShadowText(textFont, textBuffer, Resize(860, 187 + i * 66, 955, 207 + i * 66), Resize(1, 1, 0, 0)); DrawShadowText(textFont, textBuffer, Resize(860, 187 + i * 66, 955, 207 + i * 66), Resize(1, 1, 0, 0));
myswprintf(textBuffer, L"%ls", availBuffer); myswprintf(textBuffer, L"%ls", availBuffer);
DrawShadowText(textFont, textBuffer, Resize(860, 209 + i * 66, 955, 229 + i * 66), Resize(1, 1, 0, 0)); DrawShadowText(textFont, textBuffer, Resize(860, 209 + i * 66, 955, 229 + i * 66), Resize(1, 1, 0, 0));
......
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 {
...@@ -96,8 +97,8 @@ public: ...@@ -96,8 +97,8 @@ public:
static HostResult ParseHost(char *hostname); static HostResult ParseHost(char *hostname);
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);
#ifdef YGOPRO_MESSAGE_DEBUG #ifdef YGOPRO_MESSAGE_DEBUG
printf("CTOS: %d\n", proto); printf("CTOS: %d\n", proto);
#endif #endif
...@@ -107,8 +108,8 @@ public: ...@@ -107,8 +108,8 @@ public:
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));
#ifdef YGOPRO_MESSAGE_DEBUG #ifdef YGOPRO_MESSAGE_DEBUG
printf("CTOS: %d Length: %ld\n", proto, sizeof(ST)); printf("CTOS: %d Length: %ld\n", proto, sizeof(ST));
...@@ -119,8 +120,8 @@ public: ...@@ -119,8 +120,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);
#ifdef YGOPRO_MESSAGE_DEBUG #ifdef YGOPRO_MESSAGE_DEBUG
printf("CTOS: %d Length: %ld\n", proto, len); printf("CTOS: %d Length: %ld\n", proto, len);
......
...@@ -411,7 +411,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -411,7 +411,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
} }
} else { } else {
selectable_cards.clear(); selectable_cards.clear();
conti_selecting = false; bool is_continuous = false;
switch(command_location) { switch(command_location) {
case LOCATION_DECK: { case LOCATION_DECK: {
for(size_t i = 0; i < deck[command_controler].size(); ++i) for(size_t i = 0; i < deck[command_controler].size(); ++i)
...@@ -438,15 +438,15 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -438,15 +438,15 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
break; break;
} }
case POSITION_HINT: { case POSITION_HINT: {
is_continuous = true;
selectable_cards = conti_cards; selectable_cards = conti_cards;
std::sort(selectable_cards.begin(), selectable_cards.end()); std::sort(selectable_cards.begin(), selectable_cards.end());
auto eit = std::unique(selectable_cards.begin(), selectable_cards.end()); auto eit = std::unique(selectable_cards.begin(), selectable_cards.end());
selectable_cards.erase(eit, selectable_cards.end()); selectable_cards.erase(eit, selectable_cards.end());
conti_selecting = true;
break; break;
} }
} }
if(!conti_selecting) { if (!is_continuous) {
mainGame->wCardSelect->setText(dataManager.GetSysString(566)); mainGame->wCardSelect->setText(dataManager.GetSysString(566));
list_command = COMMAND_ACTIVATE; list_command = COMMAND_ACTIVATE;
} else { } else {
...@@ -454,7 +454,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -454,7 +454,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
list_command = COMMAND_OPERATION; list_command = COMMAND_OPERATION;
} }
std::sort(selectable_cards.begin(), selectable_cards.end(), ClientCard::client_card_sort); std::sort(selectable_cards.begin(), selectable_cards.end(), ClientCard::client_card_sort);
ShowSelectCard(true, true); ShowSelectCard(true, is_continuous);
} }
break; break;
} }
...@@ -907,7 +907,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -907,7 +907,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
// image // image
if(selectable_cards[i + pos]->code) if(selectable_cards[i + pos]->code)
mainGame->btnCardSelect[i]->setImage(imageManager.GetTexture(selectable_cards[i + pos]->code)); mainGame->btnCardSelect[i]->setImage(imageManager.GetTexture(selectable_cards[i + pos]->code));
else if(conti_selecting) else if(select_continuous)
mainGame->btnCardSelect[i]->setImage(imageManager.GetTexture(selectable_cards[i + pos]->chain_code)); mainGame->btnCardSelect[i]->setImage(imageManager.GetTexture(selectable_cards[i + pos]->chain_code));
else else
mainGame->btnCardSelect[i]->setImage(imageManager.tCover[selectable_cards[i + pos]->controler + 2]); mainGame->btnCardSelect[i]->setImage(imageManager.tCover[selectable_cards[i + pos]->controler + 2]);
...@@ -920,8 +920,8 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -920,8 +920,8 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
else else
myswprintf(formatBuffer, L""); myswprintf(formatBuffer, L"");
} else { } else {
if(conti_selecting) if(select_continuous)
myswprintf(formatBuffer, L"%ls", DataManager::unknown_string); myswprintf(formatBuffer, L"%ls", dataManager.unknown_string);
else if(cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE) else if(cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE)
myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0)); myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0));
else if(selectable_cards[i + pos]->location == LOCATION_OVERLAY) else if(selectable_cards[i + pos]->location == LOCATION_OVERLAY)
...@@ -936,7 +936,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -936,7 +936,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
} }
mainGame->stCardPos[i]->setText(formatBuffer); mainGame->stCardPos[i]->setText(formatBuffer);
// color // color
if(conti_selecting) if(select_continuous)
mainGame->stCardPos[i]->setBackgroundColor(0xffffffff); mainGame->stCardPos[i]->setBackgroundColor(0xffffffff);
else if(selectable_cards[i + pos]->location == LOCATION_OVERLAY) { else if(selectable_cards[i + pos]->location == LOCATION_OVERLAY) {
if(selectable_cards[i + pos]->owner != selectable_cards[i + pos]->overlayTarget->controler) if(selectable_cards[i + pos]->owner != selectable_cards[i + pos]->overlayTarget->controler)
...@@ -1614,7 +1614,9 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -1614,7 +1614,9 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
myswprintf(formatBuffer, L"\nLINK-%d", mcard->link); myswprintf(formatBuffer, L"\nLINK-%d", mcard->link);
str.append(formatBuffer); str.append(formatBuffer);
} }
myswprintf(formatBuffer, L" %ls/%ls", dataManager.FormatRace(mcard->race).c_str(), dataManager.FormatAttribute(mcard->attribute).c_str()); const auto& race = dataManager.FormatRace(mcard->race);
const auto& attribute = dataManager.FormatAttribute(mcard->attribute);
myswprintf(formatBuffer, L" %ls/%ls", race.c_str(), attribute.c_str());
str.append(formatBuffer); str.append(formatBuffer);
if(mcard->location == LOCATION_HAND && (mcard->type & TYPE_PENDULUM)) { if(mcard->location == LOCATION_HAND && (mcard->type & TYPE_PENDULUM)) {
myswprintf(formatBuffer, L"\n%d/%d", mcard->lscale, mcard->rscale); myswprintf(formatBuffer, L"\n%d/%d", mcard->lscale, mcard->rscale);
...@@ -1639,10 +1641,14 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -1639,10 +1641,14 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
myswprintf(formatBuffer, L"\n%ls%d", dataManager.GetSysString(211), mcard->chValue); myswprintf(formatBuffer, L"\n%ls%d", dataManager.GetSysString(211), mcard->chValue);
else if(mcard->cHint == CHINT_CARD) else if(mcard->cHint == CHINT_CARD)
myswprintf(formatBuffer, L"\n%ls%ls", dataManager.GetSysString(212), dataManager.GetName(mcard->chValue)); myswprintf(formatBuffer, L"\n%ls%ls", dataManager.GetSysString(212), dataManager.GetName(mcard->chValue));
else if(mcard->cHint == CHINT_RACE) else if(mcard->cHint == CHINT_RACE) {
myswprintf(formatBuffer, L"\n%ls%ls", dataManager.GetSysString(213), dataManager.FormatRace(mcard->chValue).c_str()); const auto& race = dataManager.FormatRace(mcard->chValue);
else if(mcard->cHint == CHINT_ATTRIBUTE) myswprintf(formatBuffer, L"\n%ls%ls", dataManager.GetSysString(213), race.c_str());
myswprintf(formatBuffer, L"\n%ls%ls", dataManager.GetSysString(214), dataManager.FormatAttribute(mcard->chValue).c_str()); }
else if(mcard->cHint == CHINT_ATTRIBUTE) {
const auto& attribute = dataManager.FormatAttribute(mcard->chValue);
myswprintf(formatBuffer, L"\n%ls%ls", dataManager.GetSysString(214), attribute.c_str());
}
else if(mcard->cHint == CHINT_NUMBER) else if(mcard->cHint == CHINT_NUMBER)
myswprintf(formatBuffer, L"\n%ls%d", dataManager.GetSysString(215), mcard->chValue); myswprintf(formatBuffer, L"\n%ls%d", dataManager.GetSysString(215), mcard->chValue);
str.append(formatBuffer); str.append(formatBuffer);
......
This diff is collapsed.
...@@ -28,15 +28,15 @@ ...@@ -28,15 +28,15 @@
#include <functional> #include <functional>
#ifndef YGOPRO_DEFAULT_DUEL_RULE #ifndef YGOPRO_DEFAULT_DUEL_RULE
#define YGOPRO_DEFAULT_DUEL_RULE 5 #define YGOPRO_DEFAULT_DUEL_RULE CURRENT_RULE
#endif #endif
#define DEFAULT_DUEL_RULE YGOPRO_DEFAULT_DUEL_RULE namespace ygo {
constexpr int DEFAULT_DUEL_RULE = YGOPRO_DEFAULT_DUEL_RULE;
constexpr int CONFIG_LINE_SIZE = 1024; constexpr int CONFIG_LINE_SIZE = 1024;
constexpr int TEXT_LINE_SIZE = 256; constexpr int TEXT_LINE_SIZE = 256;
namespace ygo {
template<size_t N> template<size_t N>
bool IsExtension(const wchar_t* filename, const wchar_t(&extension)[N]) { bool IsExtension(const wchar_t* filename, const wchar_t(&extension)[N]) {
auto flen = std::wcslen(filename); auto flen = std::wcslen(filename);
......
...@@ -16,9 +16,13 @@ ...@@ -16,9 +16,13 @@
#include <sstream> #include <sstream>
#endif #endif
#if defined(_WIN32) && (!defined(WDK_NTDDI_VERSION) || (WDK_NTDDI_VERSION < 0x0A000005)) // Redstone 4, Version 1803, Build 17134.
#error "This program requires the Windows 10 SDK version 1803 or above to compile on Windows. Otherwise, non-ASCII characters will not be displayed or processed correctly."
#endif
unsigned int enable_log = 0x3; unsigned int enable_log = 0x3;
bool expansions_specified = false;
std::vector<std::wstring> expansions_list; std::vector<std::wstring> expansions_list;
std::vector<std::wstring> extra_script_list;
#ifndef YGOPRO_SERVER_MODE #ifndef YGOPRO_SERVER_MODE
bool exit_on_return = false; bool exit_on_return = false;
bool auto_watch_mode = false; bool auto_watch_mode = false;
...@@ -36,11 +40,11 @@ void ClickButton(irr::gui::IGUIElement* btn) { ...@@ -36,11 +40,11 @@ void ClickButton(irr::gui::IGUIElement* btn) {
#endif //YGOPRO_SERVER_MODE #endif //YGOPRO_SERVER_MODE
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
#if defined(FOPEN_WINDOWS_SUPPORT_UTF8) #if defined(_WIN32)
std::setlocale(LC_CTYPE, ".UTF-8"); std::setlocale(LC_CTYPE, ".UTF-8");
#elif defined(__APPLE__) #elif defined(__APPLE__)
std::setlocale(LC_CTYPE, "UTF-8"); std::setlocale(LC_CTYPE, "UTF-8");
#elif !defined(_WIN32) #else
std::setlocale(LC_CTYPE, ""); std::setlocale(LC_CTYPE, "");
#endif #endif
#if defined __APPLE__ && !defined YGOPRO_SERVER_MODE #if defined __APPLE__ && !defined YGOPRO_SERVER_MODE
...@@ -81,36 +85,59 @@ int main(int argc, char* argv[]) { ...@@ -81,36 +85,59 @@ int main(int argc, char* argv[]) {
ygo::Game _game; ygo::Game _game;
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
enable_log = 1; enable_log = 1;
bool expansions_specified = false;
wchar_t* expansions_env_val = nullptr; auto trim = [](std::wstring& s) {
const wchar_t* ws = L" \t\r\n";
auto b = s.find_first_not_of(ws);
auto e = s.find_last_not_of(ws);
if (b == std::wstring::npos) { s.clear(); return; }
s = s.substr(b, e - b + 1);
};
auto parse_wcsv = [&](const std::wstring& wcsv, std::vector<std::wstring>& out) {
if (wcsv.empty()) return;
std::wstringstream ss(wcsv);
std::wstring item;
while (std::getline(ss, item, L',')) {
trim(item);
if (!item.empty()) out.push_back(item);
}
};
auto get_env_wstr = [&](const char* env_name) -> std::wstring {
#ifdef _WIN32 #ifdef _WIN32
expansions_env_val = _wgetenv(L"YGOPRO_EXPANSIONS"); auto envname_w_len = std::strlen(env_name) + 1;
wchar_t* envname_w = new wchar_t[envname_w_len];
BufferIO::DecodeUTF8String(env_name, envname_w, envname_w_len);
const wchar_t* wval = _wgetenv(envname_w);
delete[] envname_w;
return (wval && wval[0]) ? std::wstring(wval) : std::wstring();
#else #else
const char* env_utf8 = std::getenv("YGOPRO_EXPANSIONS"); const char* env_utf8 = std::getenv(env_name);
if(env_utf8) { if (!env_utf8 || !env_utf8[0]) return {};
expansions_env_val = (wchar_t*)malloc(1024 * sizeof(wchar_t)); auto env_w_len = std::strlen(env_utf8) + 1;
BufferIO::DecodeUTF8String(env_utf8, expansions_env_val, 1024); wchar_t* env_w = new wchar_t[env_w_len];
} BufferIO::DecodeUTF8String(env_utf8, env_w, env_w_len);
auto res = std::wstring(env_w);
delete[] env_w;
return res;
#endif #endif
};
if (expansions_env_val && expansions_env_val[0] != L'\0') { auto load_env_list = [&](const char* env_name, std::vector<std::wstring>& out) {
expansions_specified = true; std::wstring val = get_env_wstr(env_name);
std::wstringstream ss(expansions_env_val); parse_wcsv(val, out);
std::wstring item; };
while (std::getline(ss, item, L',')) {
if (!item.empty()) { load_env_list("YGOPRO_EXPANSIONS", expansions_list);
expansions_list.push_back(item); if (expansions_list.empty()) {
}
}
} else {
expansions_specified = false;
expansions_list.push_back(L"./expansions"); expansions_list.push_back(L"./expansions");
#if defined(SERVER_PRO3_SUPPORT) && !defined(_WIN32) && !defined(__APPLE__) #if defined(SERVER_PRO3_SUPPORT) && !defined(_WIN32) && !defined(__APPLE__)
expansions_list.push_back(L"./Expansions"); expansions_list.push_back(L"./Expansions");
#endif #endif
} }
load_env_list("YGOPRO_EXTRA_SCRIPT", extra_script_list);
ygo::server_port = 7911; ygo::server_port = 7911;
ygo::replay_mode = 0; ygo::replay_mode = 0;
ygo::duel_flags = 0; ygo::duel_flags = 0;
...@@ -215,6 +242,7 @@ int main(int argc, char* argv[]) { ...@@ -215,6 +242,7 @@ int main(int argc, char* argv[]) {
bool keep_on_return = false; bool keep_on_return = false;
bool deckCategorySpecified = false; bool deckCategorySpecified = false;
bool expansions_specified = false;
expansions_list.push_back(L"./expansions"); expansions_list.push_back(L"./expansions");
for(int i = 1; i < wargc; ++i) { for(int i = 1; i < wargc; ++i) {
if (wargc == 2 && std::wcslen(wargv[1]) >= 4) { if (wargc == 2 && std::wcslen(wargv[1]) >= 4) {
...@@ -350,6 +378,12 @@ int main(int argc, char* argv[]) { ...@@ -350,6 +378,12 @@ int main(int argc, char* argv[]) {
expansions_list.push_back(wargv[i]); expansions_list.push_back(wargv[i]);
} }
continue; continue;
} else if (!std::wcscmp(wargv[i], L"--extra-script")) { // specify extra script
++i;
if(i < wargc) {
extra_script_list.push_back(wargv[i]);
}
continue;
} }
} }
ygo::mainGame->MainLoop(); ygo::mainGame->MainLoop();
......
This diff is collapsed.
...@@ -57,6 +57,7 @@ public: ...@@ -57,6 +57,7 @@ public:
irr::video::ITexture* tTarget; irr::video::ITexture* tTarget;
irr::video::ITexture* tChainTarget; irr::video::ITexture* tChainTarget;
irr::video::ITexture* tLim; irr::video::ITexture* tLim;
irr::video::ITexture* tLimCredit;
irr::video::ITexture* tOT; irr::video::ITexture* tOT;
irr::video::ITexture* tHand[3]; irr::video::ITexture* tHand[3];
irr::video::ITexture* tBackGround; irr::video::ITexture* tBackGround;
......
...@@ -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) {
...@@ -365,9 +365,9 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -365,9 +365,9 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
int flag = 0; int flag = 0;
flag += (mainGame->chkBotHand->isChecked() ? 0x1 : 0); flag += (mainGame->chkBotHand->isChecked() ? 0x1 : 0);
char arg2[8]; char arg2[8];
std::snprintf(arg2, sizeof arg2, "%d", flag); mysnprintf(arg2, "%d", flag);
char arg3[8]; char arg3[8];
std::snprintf(arg3, sizeof arg3, "%d", mainGame->gameConf.serverport); mysnprintf(arg3, "%d", mainGame->gameConf.serverport);
execl("./bot", "bot", arg1, arg2, arg3, nullptr); execl("./bot", "bot", arg1, arg2, arg3, nullptr);
std::exit(0); std::exit(0);
} else { } else {
...@@ -411,8 +411,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -411,8 +411,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);
...@@ -421,7 +420,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -421,7 +420,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);
...@@ -471,7 +470,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -471,7 +470,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
if(prev_operation == BUTTON_RENAME_REPLAY) { if(prev_operation == BUTTON_RENAME_REPLAY) {
wchar_t newname[256]; wchar_t newname[256];
BufferIO::CopyWideString(mainGame->ebRSName->getText(), newname); BufferIO::CopyWideString(mainGame->ebRSName->getText(), newname);
if(mywcsncasecmp(newname + std::wcslen(newname) - 4, L".yrp", 4)) { if (!IsExtension(newname, L".yrp")) {
myswprintf(newname, L"%ls.yrp", mainGame->ebRSName->getText()); myswprintf(newname, L"%ls.yrp", mainGame->ebRSName->getText());
} }
if(Replay::RenameReplay(mainGame->lstReplayList->getListItem(prev_sel), newname)) { if(Replay::RenameReplay(mainGame->lstReplayList->getListItem(prev_sel), newname)) {
......
...@@ -21,7 +21,7 @@ class FileSystem { ...@@ -21,7 +21,7 @@ class FileSystem {
public: public:
static void SafeFileName(wchar_t* wfile) { static void SafeFileName(wchar_t* wfile) {
while((wfile = std::wcspbrk(wfile, L"<>:\"/\\|?*")) != nullptr) while((wfile = std::wcspbrk(wfile, L"<>:\"/\\|?*")) != nullptr)
*wfile++ = '_'; *wfile++ = L'_';
} }
static bool IsFileExists(const wchar_t* wfile) { static bool IsFileExists(const wchar_t* wfile) {
...@@ -125,7 +125,7 @@ class FileSystem { ...@@ -125,7 +125,7 @@ class FileSystem {
public: public:
static void SafeFileName(wchar_t* wfile) { static void SafeFileName(wchar_t* wfile) {
while((wfile = std::wcspbrk(wfile, L"/")) != nullptr) while((wfile = std::wcspbrk(wfile, L"/")) != nullptr)
*wfile++ = '_'; *wfile++ = L'_';
} }
static bool IsFileExists(const char* file) { static bool IsFileExists(const char* file) {
...@@ -182,7 +182,7 @@ public: ...@@ -182,7 +182,7 @@ public:
bool success = true; bool success = true;
TraversalDir(dir, [dir, &success](const char *name, bool isdir) { TraversalDir(dir, [dir, &success](const char *name, bool isdir) {
char full_path[1024]; char full_path[1024];
int len = std::snprintf(full_path, sizeof full_path, "%s/%s", dir, name); int len = mysnprintf(full_path, "%s/%s", dir, name);
if (len < 0 || len >= (int)(sizeof full_path)) { if (len < 0 || len >= (int)(sizeof full_path)) {
success = false; success = false;
return; return;
...@@ -234,7 +234,7 @@ public: ...@@ -234,7 +234,7 @@ public:
file_unit funit; file_unit funit;
#endif #endif
char fname[1024]; char fname[1024];
int len = std::snprintf(fname, sizeof fname, "%s/%s", path, dirp->d_name); int len = mysnprintf(fname, "%s/%s", path, dirp->d_name);
if (len < 0 || len >= (int)(sizeof fname)) if (len < 0 || len >= (int)(sizeof fname))
continue; continue;
stat(fname, &fileStat); stat(fname, &fileStat);
......
...@@ -95,7 +95,7 @@ bool NetServer::StartServer(unsigned short port) { ...@@ -95,7 +95,7 @@ bool NetServer::StartServer(unsigned short port) {
std::memset(&sin, 0, sizeof sin); std::memset(&sin, 0, sizeof sin);
server_port = port; server_port = port;
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
#ifdef SERVER_PRO2_SUPPORT #if defined(SERVER_PRO2_SUPPORT) && !defined(SERVER_PRO3_SUPPORT)
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
#else #else
sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_addr.s_addr = htonl(INADDR_ANY);
...@@ -272,7 +272,7 @@ void NetServer::DisconnectPlayer(DuelPlayer* dp) { ...@@ -272,7 +272,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);
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
if((pktType != CTOS_SURRENDER) && (pktType != CTOS_CHAT) && (pktType != CTOS_REQUEST_FIELD) && (dp->state == 0xff || (dp->state && dp->state != pktType))) if((pktType != CTOS_SURRENDER) && (pktType != CTOS_CHAT) && (pktType != CTOS_REQUEST_FIELD) && (dp->state == 0xff || (dp->state && dp->state != pktType)))
#else #else
...@@ -352,7 +352,7 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len) { ...@@ -352,7 +352,7 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len) {
// for other server & reverse proxy use only // for other server & reverse proxy use only
/* /*
wchar_t hostname[LEN_HOSTNAME]; wchar_t hostname[LEN_HOSTNAME];
uint32_t real_ip = ntohl(BufferIO::ReadInt32(pdata)); uint32_t real_ip = ntohl(BufferIO::Read<int32_t>(pdata));
BufferIO::CopyCharArray((uint16_t*)pdata, hostname); BufferIO::CopyCharArray((uint16_t*)pdata, hostname);
*/ */
break; break;
...@@ -488,8 +488,9 @@ size_t NetServer::CreateChatPacket(unsigned char* src, int src_size, unsigned ch ...@@ -488,8 +488,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 {
...@@ -49,8 +50,8 @@ public: ...@@ -49,8 +50,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);
...@@ -59,8 +60,8 @@ public: ...@@ -59,8 +60,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)
...@@ -70,8 +71,8 @@ public: ...@@ -70,8 +71,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,14 @@ ...@@ -9,14 +9,14 @@
#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 MAX_DATA_SIZE = UINT16_MAX - 1; constexpr int SIZE_NETWORK_BUFFER = 0x20000;
constexpr int MAINC_MAX = 250; // the limit of card_state constexpr int MAX_DATA_SIZE = UINT16_MAX - 1;
constexpr int SIDEC_MAX = MAINC_MAX;
struct HostInfo { struct HostInfo {
uint32_t lflist{}; uint32_t lflist{};
......
...@@ -73,7 +73,7 @@ end ...@@ -73,7 +73,7 @@ end
end end
if BUILD_FREETYPE then if BUILD_FREETYPE then
includedirs { "../freetype/include" } includedirs { "../freetype/custom", "../freetype/include" }
else else
includedirs { FREETYPE_INCLUDE_DIR } includedirs { FREETYPE_INCLUDE_DIR }
libdirs { FREETYPE_LIB_DIR } libdirs { FREETYPE_LIB_DIR }
...@@ -114,10 +114,12 @@ end ...@@ -114,10 +114,12 @@ end
end end
filter "system:windows" filter "system:windows"
if not SERVER_PRO3_SUPPORT then
entrypoint "mainCRTStartup" entrypoint "mainCRTStartup"
end
defines { "_IRR_WCHAR_FILESYSTEM" } defines { "_IRR_WCHAR_FILESYSTEM" }
files "ygopro.rc" files "ygopro.rc"
if SERVER_PRO2_SUPPORT then if SERVER_PRO2_SUPPORT and not SERVER_PRO3_SUPPORT then
targetname ("AI.Server") targetname ("AI.Server")
end end
if SERVER_MODE then if SERVER_MODE then
......
#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 {
...@@ -23,23 +23,6 @@ void Replay::BeginRecord() { ...@@ -23,23 +23,6 @@ void Replay::BeginRecord() {
#endif #endif
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);
#ifdef YGOPRO_SERVER_MODE
time_t nowtime = time(nullptr);
struct tm *localedtime = localtime(&nowtime);
wchar_t tmppath[80];
wcsftime(tmppath, 80, L"./replay/%Y-%m-%d %H-%M-%S %%u.yrp", localedtime);
wchar_t path[80];
myswprintf(path, tmppath, server_port);
recording_fp = CreateFileW(path, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, nullptr);
#else
recording_fp = CreateFileW(L"./replay/_LastReplay.yrp", GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, nullptr);
#endif //YGOPRO_SERVER_MODE
if(recording_fp == INVALID_HANDLE_VALUE)
return;
#else
if(is_recording) if(is_recording)
std::fclose(fp); std::fclose(fp);
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
...@@ -55,7 +38,6 @@ void Replay::BeginRecord() { ...@@ -55,7 +38,6 @@ void Replay::BeginRecord() {
#endif //YGOPRO_SERVER_MODE #endif //YGOPRO_SERVER_MODE
if(!fp) if(!fp)
return; return;
#endif
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
} }
#endif //YGOPRO_SERVER_MODE #endif //YGOPRO_SERVER_MODE
...@@ -67,13 +49,8 @@ void Replay::WriteHeader(ExtendedReplayHeader& header) { ...@@ -67,13 +49,8 @@ void Replay::WriteHeader(ExtendedReplayHeader& header) {
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
if(!(replay_mode & REPLAY_MODE_SAVE_IN_SERVER)) return; if(!(replay_mode & REPLAY_MODE_SAVE_IN_SERVER)) return;
#endif #endif
#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)
...@@ -85,14 +62,9 @@ void Replay::WriteData(const void* data, size_t length, bool flush) { ...@@ -85,14 +62,9 @@ void Replay::WriteData(const void* data, size_t length, bool flush) {
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
if(!(replay_mode & REPLAY_MODE_SAVE_IN_SERVER)) return; if(!(replay_mode & REPLAY_MODE_SAVE_IN_SERVER)) return;
#endif #endif
#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);
...@@ -103,10 +75,7 @@ void Replay::Flush() { ...@@ -103,10 +75,7 @@ void Replay::Flush() {
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
if(!(replay_mode & REPLAY_MODE_SAVE_IN_SERVER)) return; if(!(replay_mode & REPLAY_MODE_SAVE_IN_SERVER)) return;
#endif #endif
#ifdef _WIN32
#else
std::fflush(fp); std::fflush(fp);
#endif
} }
void Replay::EndRecord() { void Replay::EndRecord() {
if(!is_recording) if(!is_recording)
...@@ -114,11 +83,7 @@ void Replay::EndRecord() { ...@@ -114,11 +83,7 @@ void Replay::EndRecord() {
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
if(replay_mode & REPLAY_MODE_SAVE_IN_SERVER) { if(replay_mode & REPLAY_MODE_SAVE_IN_SERVER) {
#endif #endif
#ifdef _WIN32
CloseHandle(recording_fp);
#else
std::fclose(fp); std::fclose(fp);
#endif
#ifdef YGOPRO_SERVER_MODE #ifdef YGOPRO_SERVER_MODE
} }
#endif #endif
...@@ -133,24 +98,30 @@ void Replay::EndRecord() { ...@@ -133,24 +98,30 @@ void Replay::EndRecord() {
} }
is_recording = false; is_recording = false;
} }
void Replay::SaveReplay(const wchar_t* name) { bool Replay::SaveReplay(const wchar_t* base_name) {
if(!FileSystem::IsDirExists(L"./replay") && !FileSystem::MakeDir(L"./replay")) if(!FileSystem::IsDirExists(L"./replay") && !FileSystem::MakeDir(L"./replay"))
return; return false;
wchar_t fname[256]; wchar_t filename[256]{};
myswprintf(fname, L"./replay/%ls.yrp", name); wchar_t path[256]{};
FILE* rfp = mywfopen(fname, "wb"); BufferIO::CopyWideString(base_name, filename);
FileSystem::SafeFileName(filename);
if (myswprintf(path, L"./replay/%ls.yrp", filename) <= 0)
return false;
FILE* rfp = mywfopen(path, "wb");
if(!rfp) if(!rfp)
return; return false;
std::fwrite(&pheader, sizeof pheader, 1, rfp); std::fwrite(&pheader, sizeof pheader, 1, rfp);
std::fwrite(comp_data, comp_size, 1, rfp); std::fwrite(comp_data, comp_size, 1, rfp);
std::fclose(rfp); std::fclose(rfp);
return true;
} }
#ifndef YGOPRO_SERVER_MODE #ifndef YGOPRO_SERVER_MODE
bool Replay::OpenReplay(const wchar_t* name) { bool Replay::OpenReplay(const wchar_t* name) {
FILE* rfp = mywfopen(name, "rb"); FILE* rfp = mywfopen(name, "rb");
if(!rfp) { if(!rfp) {
wchar_t fname[256]; wchar_t fname[256];
myswprintf(fname, L"./replay/%ls", name); if (myswprintf(fname, L"./replay/%ls", name) <= 0)
return false;
rfp = mywfopen(fname, "rb"); rfp = mywfopen(fname, "rb");
} }
if(!rfp) if(!rfp)
...@@ -202,26 +173,30 @@ bool Replay::OpenReplay(const wchar_t* name) { ...@@ -202,26 +173,30 @@ bool Replay::OpenReplay(const wchar_t* name) {
return true; return true;
} }
bool Replay::DeleteReplay(const wchar_t* name) { bool Replay::DeleteReplay(const wchar_t* name) {
if (std::wcschr(name, L'/') || std::wcschr(name, L'\\'))
return false;
wchar_t fname[256]; wchar_t fname[256];
myswprintf(fname, L"./replay/%ls", name); if(myswprintf(fname, L"./replay/%ls", name) <= 0)
return false;
return FileSystem::RemoveFile(fname); return FileSystem::RemoveFile(fname);
} }
bool Replay::RenameReplay(const wchar_t* oldname, const wchar_t* newname) { bool Replay::RenameReplay(const wchar_t* oldname, const wchar_t* newname) {
wchar_t oldfname[256]; wchar_t old_path[256];
wchar_t newfname[256]; wchar_t new_path[256];
myswprintf(oldfname, L"./replay/%ls", oldname); if (std::wcschr(oldname, L'/') || std::wcschr(oldname, L'\\'))
myswprintf(newfname, L"./replay/%ls", newname); return false;
#ifdef _WIN32 if (std::wcschr(newname, L'/') || std::wcschr(newname, L'\\'))
BOOL result = MoveFileW(oldfname, newfname); return false;
return !!result; if (myswprintf(old_path, L"./replay/%ls", oldname) <= 0)
#else return false;
char oldfilefn[256]; if (myswprintf(new_path, L"./replay/%ls", newname) <= 0)
char newfilefn[256]; return false;
BufferIO::EncodeUTF8(oldfname, oldfilefn); char oldfilefn[1024];
BufferIO::EncodeUTF8(newfname, newfilefn); char newfilefn[1024];
int result = rename(oldfilefn, newfilefn); BufferIO::EncodeUTF8(old_path, oldfilefn);
BufferIO::EncodeUTF8(new_path, newfilefn);
int result = std::rename(oldfilefn, newfilefn);
return result == 0; return result == 0;
#endif
} }
bool Replay::ReadNextResponse(unsigned char resp[]) { bool Replay::ReadNextResponse(unsigned char resp[]) {
unsigned char len{}; unsigned char len{};
......
#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 {
...@@ -71,7 +74,7 @@ public: ...@@ -71,7 +74,7 @@ public:
void WriteInt32(int32_t data, bool flush = true); void WriteInt32(int32_t data, bool flush = true);
void Flush(); void Flush();
void EndRecord(); void EndRecord();
void SaveReplay(const wchar_t* name); bool SaveReplay(const wchar_t* base_name);
// play // play
static bool DeleteReplay(const wchar_t* name); static bool DeleteReplay(const wchar_t* name);
...@@ -108,10 +111,6 @@ public: ...@@ -108,10 +111,6 @@ public:
#endif // YGOPRO_SERVER_MODE #endif // YGOPRO_SERVER_MODE
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.
#include "serverapi.h" #include "serverapi.h"
#include "game.h"
#include "netserver.h"
#include "network.h"
#include "config.h"
#include "data_manager.h"
#include "gframe.h"
#include <event2/thread.h>
#include <memory>
namespace ygo { namespace ygo {
extern "C" DECL_DLLEXPORT int start_server(const char* args) { YGOSERVER_API int start_server(const char* args) {
int argc = 1; int argc = 1;
char** argv = new char* [13]; char** argv = new char* [13];
const char* server_name = "ygoserver"; const char* server_name = "ygoserver";
...@@ -36,7 +44,7 @@ namespace ygo { ...@@ -36,7 +44,7 @@ namespace ygo {
return result; return result;
} }
extern "C" DECL_DLLEXPORT void stop_server() { YGOSERVER_API void stop_server() {
NetServer::StopServer(); NetServer::StopServer();
} }
} }
#ifndef SERVERAPI_H #ifndef SERVERAPI_H
#define SERVERAPI_H #define SERVERAPI_H
#include "game.h" #ifdef __cplusplus
#include "netserver.h" #define EXTERN_C extern "C"
#include "network.h" #else
#include "config.h" #define EXTERN_C
#include "data_manager.h" #endif
#include "gframe.h"
#include <event2/thread.h>
#include <memory>
#ifdef WIN32 #ifndef YGOSERVER_API
#define DECL_DLLEXPORT __declspec(dllexport) #if defined(__EMSCRIPTEN__)
#include <emscripten/emscripten.h>
#define YGOSERVER_API EXTERN_C EMSCRIPTEN_KEEPALIVE
#elif defined(_WIN32)
#define YGOSERVER_API EXTERN_C __declspec(dllexport)
#else #else
#define DECL_DLLEXPORT #define YGOSERVER_API EXTERN_C __attribute__ ((visibility ("default")))
#endif #endif
#endif
namespace ygo { namespace ygo {
extern "C" DECL_DLLEXPORT int start_server(const char* args); YGOSERVER_API int start_server(const char* args);
extern "C" DECL_DLLEXPORT void stop_server(); YGOSERVER_API void stop_server();
} }
#endif // !SERVERAPI_H #endif // !SERVERAPI_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Subproject commit 3a51f3203f767536cbeeb5dfc52a8dcf449be9f7 Subproject commit 56c7569a1cd6f7fe482bd5bcb9961346c3e9a7c0
...@@ -10,9 +10,6 @@ project "event" ...@@ -10,9 +10,6 @@ project "event"
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
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" } includedirs { "include", "compat" }
......
/****************************************************************************
*
* ft2build.h
*
* FreeType 2 build and setup macros.
*
* Use custom/ft2build.h instead of the default include/freetype/ft2build.h
* to customize the FreeType 2 build of YGOPro.
*
*/
#ifndef FT2_BUILD_MY_PLATFORM_H_
#define FT2_BUILD_MY_PLATFORM_H_
#define FT_CONFIG_OPTIONS_H <ygopro/ftoption.h>
#define FT_CONFIG_MODULES_H <ygopro/ftmodule.h>
#include <freetype/config/ftheader.h>
#endif /* FT2_BUILD_MY_PLATFORM_H_ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Subproject commit 49961747bbe53583deb08f969451805851a96919 Subproject commit 1ab065ebcec1d99f33fa91c067985cd8dd57baa1
This diff is collapsed.
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