ygopro源码分析1:源码的获取编译
1.简介
是⼀个开源免费的游戏王模拟器,使⽤C++14编写,原作者是Fluorohydride(圆神),可以模拟⼏乎所有的游戏王卡⽚,⽀持所有平台,主要有两个对战服务器:233服和mycard服,这⼏年来⼀直是牌佬的主要决⽃⼯具.不过科乐美的官⽅游戏"Duel Master"带着"全世界同台竞技"的功能上个⽉上线了(⽽且看样⼦挺良⼼的), ygopro 在未来可能会流失⼀些⽤户.
话说回来,ygopro的源码相当枯燥,并且注释很少,实际上啃这个没什么太⼤的实⽤性.但如果你想DIY卡⽚并且为其编写lua脚本在ygopro⾥玩耍的话,啃ygopro的源码是有很⼤的帮助的,甚⾄你可以修改"core"的源码实现更炫酷的卡⽚效果.
如果你和我⼀样只是个普通的游戏王线上玩家,只是想拆开ygopro⼀探究竟的话,也可以跟着看看打发时间.不过在这之前,你必须很了解ygopro的使⽤⽅法ygopro⼤概由三部分组成(⽤了若⼲第三⽅库):
ygopro:游戏的客户端本体
|-irrlicht:游戏引擎,负责游戏画⾯和GUI
|-freetype2:字体引擎,负责让irrlicht显⽰中⽂
|-sqlite3:轻量级数据库,存储卡⽚的数据,⽤于卡⽚的查搜寻
|-libevent2:⽹络库,实现联机对战
|-lzma:压缩算法,⽤于游戏录像⽂件(⾃带源码不需要另下载)
|-IrrKlang:⾳频引擎(可以忽略)
ocgcore:脚本处理引擎
|-lua5.3:⽤于读取各种脚本
script:lua编写的卡⽚脚本
ygopro负责所有的可见游戏内容:游戏动画界⾯UI等等,还使⽤libevent2实现了服务器和客户端,
ocgcore负责读取运⾏lua脚本,处理ocg中所有的复杂逻辑,维护duel.
core和server之间通过ocgapi.cpp⾥的函数交换信息.
所需软件列表(windows)
在这个过程中会需要很多软件,在开头列出来,⼤多都可直接搜索下载
git
visual studio:⽤于获取msvc编译器
vscode:⽂本编辑器,可选vscode_insiders 或 vscodium
Clion:IDE,⽐vscode的C++插件好⽤太多了.
sqlitebrowser:⽤于浏览card数据库
: ygopro的定制card数据库操作软件
Clion是收费的,如果有edu邮箱的话可以免费申请使⽤,没有邮箱的话,30天的免费试⽤也⾜够使⽤了.或者使⽤破解版.
如果实在⽤不上Clion的话,可以使⽤vscode+cmake插件+Cpp插件来替代它.
Clion的好⽤在于开箱即⽤的clangd和clang-tidy强⼤的补全和跳转;这点vscode是远远⽐不上的,vscode打开⼯程只会看见⼀⼤堆红⾊波浪线
但是vscode的cmake插件构筑⼯程时会同时⽣成sln⽂件,这时可以使⽤vs打开,享受到和Clion同⽔平的体验.
2.获取源码
ygopro的源码有很多分⽀,每个服⽤的都是⾃⼰fork的分⽀,跟原版不太⼀样,经过⽐较,我选择了选⽤了.因为它兼容不少服务器,有⼀些额外功能,源码感觉⽐原版要整洁⼀些,可以说是ygopro的pro版.
执⾏下⾯的命令就可以⼀键下载ygopro ocgcore script 的全部⽂件.
git clone --recurse github/purerosefallen/ygopro.git
script包含了所有的卡⽚脚本,上⾯的命令会执⾏很长时间.
我们可以使⽤本地ygopro下的script,完全不⽤另下载,只需要下载ygopro 和 ocgcore就⾏了.
git clone github/purerosefallen/ygopro.git
cd ygopro
git clone github/purerosefallen/ygopro-core.git ocgcore
3.编译
ygopro的源码同时⽀持windows linux 和macos系统,但我没试过macos.
KoishiPro默认使⽤CMake来构筑项⽬,我也建议使⽤CMake来构筑项⽬.
3.1 在linux下编译(默认64bit)
在linux下编译⽐较简单,只需要下载好相应的包,然后cmake⼀键编译构筑就⾏了,
常见的错误可能是 "不到XX的包"之类的
⼤概是因为不同的包管理器安装的包名有差异,这时,要去看⼀下⾃⼰系统对应⽬录的包名叫什么(⼀般为libxxx.a),再看⼀下中链接的包是否⼀致.
3.2 在windows下编译(默认32bit)
由于windows上并没有⾃带包管理⼯具,所以配置第三⽅库⼀般⽐较痛苦,⽹络上流传的其他编译教程⼀般都是⽤premake来构筑项⽬,让其⽣成visual studio项⽬,然后再外加⼀堆配置过程完成编译,超级⿇烦.
还好我们选择了Koishi,⽀持CMake,可以使这个过程简单不少.另外我讨厌复杂的vs,我选择使⽤简单的Clion.
环境配置
关于编译器的选择,windows上主要有两类编译器:msvc和MinGW,⼤部分ygopro的分⽀都是使⽤msvc编译的,所以我们也选msvc,安装其的最简单⽅法:下载vs,并下载C++相关SDK.
有了msvc之后,就可以去配置Clion了.
⾸先打开Clion设置⾥的⼯具链,设置两条⼯具链amd64和amd64_x86,Clion可以⾃动识别vs并⽣成,我们要做的仅仅是为两条⼯具链命名.
有了⼯具链,然后在设置⾥去设置Cmake的配置选项,⼀般会⾃动⽣成Dubug和Release.我们要做的仅仅是为其选择⼯具链,amd64 or x86.到这步,环境就配置完成了.
第三⽅库
接下来下载各个第三⽅库.
(此版本是mycard的修改版,⾃带CMakeLists)
然后我们把这些库都解压到⼯程的根⽬录下的相应⽂件夹下(这些⽂件夹需要⾃⾏修改成 event freetype irrlicht sqlite3 lua这些名字),
同时需要保证每个⽂件夹根⽬录⾥都需要有⼀个⽂件.
⽬录⼤概如下⽅所⽰:
|-ygopro
├─event
│└─
├─freetype
|  └─
├─irrlicht
|  └─
├─sqlite3
|  └─
├─lua
|  └─
现在除了lua和sqlite3之外,其余3个库都已经准备好了⽂件.
所以现在要为lua和sqlite3添加编译脚本.
#sqlite3的编译脚本
project(sqlite3)
file(GLOB SQL_SRC ./*.c)
add_library(sqlite3 STATIC ${SQL_SRC})
#lua的编译脚本
#需要删除 src/luac.c  这个是命令⾏程序,有main函数
project(lua)
file(GLOB LUA_SRC ./src/*.c)
add_library(lua STATIC ${LUA_SRC})
event的编译脚本需要做⼀些修改
#在前⾯的option部分把EVENT__DISABLE_OPENSSL打开 ,关闭对openssl的依赖
游戏免费源码分享网站option(EVENT__DISABLE_OPENSSL
"Define if libevent should build without support for OpenSSL encryption" ON)
event的编译脚本默认会编译⼀些test,我们不需要,
把995⾏ sample处以下的内容全部注释
irrlicht设置不使⽤D3D9编译
//在IrrCompileConfig.h这个⽂件 (156⾏之前) 加⼊下⾯这⾏
#define NO_IRR_COMPILE_WITH_DIRECT3D_9_
修改lua的路径
我们lua库的路径是 lua/src,ocgcore的CMakeLists需要修改成如下:
project (ocgcore)
set (AUTO_FILES_RESULT)
AutoFiles("." "src" "\\.(cpp|c|h)$")
if (MSVC)
include_directories ( ../lua/src )  #正确的lua路径
else ()
include_directories ( ${LUA_INCLUDE_DIR} )
endif ()
add_library (ocgcore STATIC ${AUTO_FILES_RESULT})
if (MSVC)
target_link_libraries (ocgcore lua)
else ()
target_link_libraries (ocgcore ${LUA_LIBRARIES})
endif ()
⼀些其他修改
lua.h相关
ocgcore是C++⼯程,应该把 interpreter.h中 14⾏改成 lua.hpp
编译
使⽤Clion编译,选择的配置是Debug+amd64_x86.
⼀些技巧
可以看到根⽬录的⾥有很多add_subdirectory,每⼀个都代表了⼀个project,为了⽅便的检测修改的是否正确,可以先把其他的
add_subdirectory注释掉,只留下⼀个,这样就可以逐个编译了.
可能会发⽣的错误
使⽤的irrlicht是mycard特殊修改的版本,如果你使⽤的是其他地⽅的irrlicht,有可能会遇到问题.
这个地⽅c_str()的返回值是char*型,和 wchar_t*不符合,会报错
const wchar_t* fname = archive->getFullFileName(j).c_str();
在合适的地⽅定义这个函数,可以将char* 转换成wchar_t*
#include <stringapiset.h>
wchar_t* AnsiToUnicode(const char* szStr)
{
int nLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szStr, -1, NULL, 0 );
if (nLen == 0)
{
return NULL;
}
wchar_t* pResult = new wchar_t[nLen];
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szStr, -1, pResult, nLen );
return pResult;
}
然后
把出错的这⾏改成
const wchar_t* fname =AnsiToUnicode( archive->getFullFileName(j).c_str());
运⾏
打开ygopro的根⽬录,将pics(卡图⽬录),script(脚本⽬录),textures(游戏素材),cards.cdb(卡⽚数据库)和各种conf⽂件都复制到我们的输出⽬录,和同级,
然后就可以运⾏了.
输⼊
<233 233
就可以和233服的玩家决⽃了.
3.3 在windows下编译64bit程序
考虑到圆神编写此程序的年份,那时windows上还全都是32bit软件, ygopro是不⽀持使⽤msvc去编译64bit程序的.能编译通过,但是⼀旦涉及到server和core的运⾏,就会出错崩溃, ⽆法建⽴主机和使⽤单⼈模式,只能当作client和其他玩家对战.
出错原因
前⾯说到,core和server之间使⽤ocgapi通信,它们之间的通信涉及到了core当中的duel指针,duel是⼀个⾮常庞⼤的class.
core被设计成dll库,server没必要把duel再实现⼀遍,所以duel指针被强制转换成了long类型,⽤于两者之间的交换.
msvc⽀持的是ILP32和ILP64,在32bit和64bit下,long都是32位的.所以32位程序中,long可以存储指针,当换成64位时,long就⽆法存储64位的指针了,当程序试图运⾏server时,就会崩溃.
解决⽅法
把存储pduel的相关变量的类型改成64位的,⽐如size_t.
然后CMake选择 Debug+amd64,就可以编译成功了,但这个完全没有必要,32的就完全⾜够了!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。