传奇源码分析.docx
- 文档编号:6247572
- 上传时间:2023-01-04
- 格式:DOCX
- 页数:63
- 大小:68.44KB
传奇源码分析.docx
《传奇源码分析.docx》由会员分享,可在线阅读,更多相关《传奇源码分析.docx(63页珍藏版)》请在冰豆网上搜索。
传奇源码分析
传奇源码分析
中龙技术论坛2012年8月15号般若收录
2010年01月30日星期六下午11:
02
简述:
最近对高性能的服务器比较感兴趣,读过了DELPHI的Socker源码WebService及RemObject之后,高性能的服务器感兴趣。
你可能需要的以下知识才能更好的读懂一个商业源码:
1).SOCKET的I/O模型熟悉掌握。
2).面向对象技术的熟悉掌握。
3).Socket的API掌握。
4).多线程技术等。
5).一门熟悉的开发工具掌握,和多种语言的源码阅读能力。
我下的源码LegendOfMir2_Server:
共包含AdminCmd,DBSrv,GameGate,GameSvr,LoginGate,LoginSvr,SelGate七个工程文件。
传奇的客户端源代码有两个工程,WindHorn和Mir2Ex。
我分析的,主要是VCSQL版本的,DELPHI翎风源码不做分析,另外下载了乐都WIL编辑器和乐都MPA地图编辑器这些工具.
传奇源码分析-客户端(WindHorn简述和传奇文件格式分析)
DirectX类库分析(WindHorn):
1. RegHandler.cpp注册表访问(读写)。
2. CWHApp派生CWHWindow,CWHWindow完成窗口的注册和创建。
CWHWindow派生出CWHDXGraphicWindow,CWHDXGraphicWindow调用CWHWindow完成创建窗口功能,然后再调用CreateDXG()来初始化DirectX。
3. WHDefProcess.cpp在构造函数中获得CWHDXGraphicWindow句柄。
Clear函数中调用在后台缓存上进行绘图操作,换页至屏幕。
ShowStatus函数,显示状态信息。
DefMainWndProc函数,调用CWHDXGraphicWindow->MainWndProcDXG消息处理。
4. WHImage.cpp图象处理。
加载位图,位图转换。
优化处理。
5. WHSurface.cpp主页面处理。
6. WHWilTexture.cpp材质渲染。
WILTextureContainer:
WIL容器类。
m_pNext指向下一个WILTextureContainer,单链表。
7. WHWilImage.cpp从Data目录中加载Wix文件(内存映射)。
8. WHDXGraphic.cpp处理DirectX效果。
文件类型格式探讨:
Wix文件:
索引文件,根据索引查找到相应数据地址(数据文件)。
//WIX文件头格式
typedefstructtagWIXFILEIMAGEINFO
{
CHAR szTmp[40]; //库文件标题'WEMADEEntertainmentinc.'WIL文件头
INT nIndexCount; //图片数量
INT* pnPosition; //位置
}WIXIMAGEINFO,*LPWIXIMAGEINFO;
我们下载一个Hedit编辑器打开一个Wil文件,分析一下。
我们发现Wix文件中,0x23地址(含该地址)以前的内容是都相同的,即为:
#INDXv1.0-WEMADEEntertainmentinc.
Ofs440x2C的地方:
存放着0B000000,高低位转换后为:
0xB转换十进制数为11(图片数量)Ofs480x30的地方:
存放着38040000,高低位转换后为:
0x438=1080,这个就是图象数据的开始位置。
我们用Wil编辑打开对应的Wil文件,发现,果然有11张图片。
另外我们发现,在Ofs=44-47之间的数据总是38040000,终于明白,所有的图片起始位置是相同的。
Wil文件:
数据文件。
前面我们说了图象数据的开始位置为0x438=1080,1080中有文件开头的44字节都是相同的。
所以,就是说有另外的1036字节是另有用途。
1036中有1024是一个256色的调色板。
我们看到图片位置数据为:
20035802,转化为十六进制:
0x320,0x258刚好就是800*600大小的图片。
0700D4FF。
图片起始位置为:
Ofs1088:
0x440图片大小为480000
起始位置:
0x4401088 终止位置:
0x7573F481087为了验证数据是否正确,我们通过Wil工具,把第一幅图片导出来,然后用Hedit编辑器打开,经过对比,我们发现,数据一致。
大小一致。
第二张BMP图片(图片起始位置:
0x43610078):
F0016901,0700D4FF
刚好大小。
第二张Wil起始位置:
Ofs:
4810960x75748
知道了图片格式,我们可以写一个抓图片格式的程序了。
传奇源码分析-客户端(全局变量与总体执行流程)
客户端:
传奇的客户端源代码有两个工程,WindHorn和Mir2Ex。
先剖析一下WindHorn工程。
1.CWHApp、CWHWindow和CWHDXGraphicWindow。
Window程序窗口的创建。
CWHApp派生CWHWindow,CWHWindow又派生CWHDXGraphicWindow。
CWHWindow类
中完成窗口的注册和创建。
CWHDXGraphicWindow调用CWHWindow完成创建窗口功能,然后再调用CreateDXG()来初始化DirectX。
2.CWHDefProcess派生出CloginProcess、CcharacterProcess、CgameProcess三个类。
这三个类是客户端处理的核心类。
3.全局变量:
CWHDXGraphicWindow g_xMainWnd;主窗口类。
CLoginProcess g_xLoginProc;登录处理。
CCharacterProcess g_xChrSelProc;角色选择处理。
CgameProcess g_xGameProc;游戏逻辑处理。
4.代码分析:
1.首先从LoginGate.cppWinMain分析:
g_xMainWnd定义为CWHDXGraphicWindow调用CWHWindow完成创建窗口功能,然后
调用DirectDrawEnumerateEx枚举显示设备,(执行回调函数DXGDriverEnumCallbackEx)再调用CreateDXG()来初始化DirectX(创建DirectDraw对象,取得独占和全屏模式,设置显示模式等)。
g_xSound.InitMirSound创建CSound对象。
g_xSpriteInfo.SetInfo();
初始化声音,加载Socket库之后,进行CWHDefProcess*指针赋值(事件绑定)。
g_bProcState变量反应了当前游戏的状态(登录,角色选择,游戏逻辑处理)。
调用Load初始化一些操作(登录,角色选择,游戏逻辑处理)。
进行消息循环。
case_LOGIN_PROC:
g_xLoginProc.RenderScene(dwDelay);
case_CHAR_SEL_PROC:
g_xChrSelProc.RenderScene(dwDelay);
case_GAME_PROC:
g_xGameProc.RenderScene(dwDelay);
根据g_bProcState变量标志,选择显示相应的画面。
2.接收处理网络消息和接收处理窗口消息。
在不同的状态下(登录,角色选择,游戏逻辑处理),接收到的消息(网络,窗口消息)会分派到不同的函数中处理的。
这里是用虚函数处理(调用子类方法,由实际的父类完成相应的处理)。
OnMessageReceive主要处理网络消息。
DefMainWndProc则处理窗体消息(按键,重绘等),创建窗体类为CWHDXGraphicWindow,回调函数为:
MainWndProc(HWNDhWnd,UINTuMsg,WPARAMwParam,LPARAMlParam)
if(m_pxDefProcess)
m_pxDefProcess->DefMainWndProc(hWnd,uMsg,wParam,lParam);
else
returnMainWndProcDXG(hWnd,uMsg,wParam,lParam);
m_pxDefProcess->DefMainWndProc调用父类的实际处理。
在WM_PAINT事件里:
g_xClientSocket
.ConnectToServer连接登陆服务器。
传奇源码分析-客户端(传奇2文件格式分析)
传奇文件类型格式探讨
(一):
Wix文件:
索引文件,根据索引查找到相应数据地址(数据文件)。
//WIX文件头格式
typedefstructtagWIXFILEIMAGEINFO
{
CHAR szTmp[40]; //库文件标题'WEMADEEntertainmentinc.'WIL文件头
INT nIndexCount; //图片数量
INT* pnPosition; //位置
}WIXIMAGEINFO,*LPWIXIMAGEINFO;
我们下载一个Hedit编辑器打开一个Wil文件,分析一下。
我们发现Wix文件中,0x23地址(含该地址)以前的内容是都相同的,即为:
#INDXv1.0-WEMADEEntertainmentinc.
Ofs440x2C的地方:
存放着0B000000,高低位转换后为:
0xB转换十进制数为11(图片数量)Ofs480x30的地方:
存放着38040000,高低位转换后为:
0x438=1080,这个就是图象数据的开始位置。
我们用Wil编辑打开对应的Wil文件,发现,果然有11张图片。
另外我们发现,在Ofs=44-47之间的数据总是38040000,终于明白,所有的图片起始位置是相同的。
Wil文件:
数据文件。
前面我们说了图象数据的开始位置为0x438=1080,1080中有文件开头的44字节都是相同的。
所以,就是说有另外的1036字节是另有用途。
1036中有1024是一个256色的调色板。
而Wil里面的图片格式都是256色的位图储存。
我们看到图片位置数据为:
20035802,转化为十六进制:
0x320,0x258刚好就是800*600大小的图片。
0700D4FF为固定值(标识)。
图片起始位置为:
Ofs1088:
0x440图片大小为480000
起始位置:
0x4401088 终止位置:
0x7573F481087为了验证数据是否正确,我们通过Wil工具,把第一幅图片导出来,然后用Hedit编辑器打开,经过对比,我们发现,数据一致。
大小一致。
大家看到图片1的结束位置为0fs481077,减去1080+1=480000刚好800*600大小。
我们用Wil抓图工具打开看一下(确定是800*600大小):
我们导出第二张BMP图片
图片的大小为:
496*361,我们从Wix中读出第二张图片的索引位置:
根据贴图,我们发现第二张图片的索引位置为:
40570700,转换为十六进制:
0x75740,即为:
481088,前面我们讲到第一张图片的结束位置是:
0fs481077,从Wix中读出来的也刚好为第二张图片的起始位置:
(我们分析Wil中的第二张图片,起始位置:
0x75740481088):
F0016901为图片长宽:
0x1F0,0x169为496*361。
0700D4FF为固定值(标识)。
我们用工具打开第二张BMP图片,从起始位置,一直选取中至结束,发现刚好选496*361字节大小。
两边数据对比之后发现一致。
知道了图片格式,我们可以写一个抓图片格式的程序了。
传奇源码分析-客户端(传奇2和3文件格式分析比较)
贴这个贴子,希望大家少走弯路。
网上下载的那个版本应该是从传奇2改的,传奇3的格式。
分析一下源码吧,g_xLoginProc.Load();之后就加载m_Image.NewLoad(IMAGE_INTERFACE_1,TRUE,TRUE);
继续读Wix文件,
ReadFile(hWixFile,&m_stNewWixImgaeInfo,sizeof(NEWWIXIMAGEINFO)-sizeof(INT*),&dwReadLen,NULL);
//WIX文件头格式(56Byte)(NEW)
typedefstructtagNEWWIXFILEIMAGEINFO
{
CHARszTitle[20]; //库文件标题'WEMADEEntertainmentinc.'WIL文件头
INTnIndexCount; //图片数量
INT*pnPosition; //位置
}NEWWIXIMAGEINFO,*LPNEWWIXIMAGEINFO;
不看不知道,一看吓一跳,大家看到了吧,这个是新的WIX的定义,不是传奇2的,前面分析过传奇2的图片:
0x23地址(含该地址)以前的内容是都相同的,即为:
#INDXv1.0-WEMADEEntertainmentinc. Ofs440x2C的地方:
存放着0B000000,高低位转换后为:
0xB转换十进制数为11(图片数量)Ofs480x30的地方:
存放着38040000,高低位转换后为:
0x438=1080,这个就是图象数据的开始位置。
这里才20个标题长度。
一看就不对。
所以如果你下了网上的传奇3的格式,试着读传奇2的图片,是不正确的。
具体大家可以调试一下,我调试过了,里面的图片数量根本不对。
汗,居然让人郁闷的是,//WIX文件头格式(56Byte)
typedefstructtagWIXFILEIMAGEINFO
{
CHARszTmp[40]; //库文件标题'WEMADEEntertainmentinc.'WIL文件头
INTnIndexCount; //图片数量
INT*pnPosition; //位置
}WIXIMAGEINFO,*LPWIXIMAGEINFO;我用了这种格式也不对。
为什么不对,因为我前面分析过了,0xB转换十进制数为11(图片数量)Ofs480x30的地方,看到没有,图片数量的存放地方。
所以赶快改一下数据结构吧,不知道为什么,难道是我版本有问题,我下了几个资源文件,结果发现问题依然存在。
看来不是图片的问题。
另外,下面的工程里的图片,如果要运行,不用改数据结构,请到传奇3客户端官方网站下载。
我下载的是1.5版的资源文件。
是传奇2的资源文件。
祝大家好运吧!
传奇文件类型格式探讨
(二):
//WIX文件头格式(NEW)
typedefstructtagNEWWIXFILEIMAGEINFO
{
CHAR szTitle[20]; //库文件标题'WEMADEEntertainmentinc.'WIL文件头
INT nIndexCount; //图片数量
INT* pnPosition; //位置
}NEWWIXIMAGEINFO,*LPNEWWIXIMAGEINFO;
我们下载一个Hedit编辑器打开一个Wil文件,分析一下。
我们发现Wix文件中,0x13地址(含该地址)以前的内容是都相同的,即为:
‘ ’20个空格。
图片数量:
nIndexCount18
Ofs20,0x14的位置,存放的数据为12000000,高低位转换后为:
0x12十制数为18(图片数量)。
Ofs280x1C的地方:
存放着20000000,高低位转换后为:
0x20=32,这个就是图象数据的开始位置。
我们用Wil编辑打开对应的Wil文件,发现,果然有17张图片(减1)。
另外我们发现,在Ofs280x1C的地方=28-31之间的数据总是20000000,终于明白,所有的图片起始位置是相同的。
抓图分析,自己就再分析一下吧,和传奇2的结构差不多。
传奇源码分析-客户端(游戏逻辑处理源分析一)
登录处理事件:
0.WinMain主函数调用g_xLoginProc.Load();加载图片等初始化,设置g_bProcState的状态。
1.CLoginProcess:
:
OnKeyDown->m_xLogin.OnKeyDown->g_xClientSocket.OnLogin;
WSAAsyncSelect模型ID_SOCKCLIENT_EVENT_MSG,因此,(登录,
角色选择,游戏逻辑处理)都回调g_xClientSocket.OnSocketMessage(wParam,lParam)进行处理。
OnSocketMessage函数中:
FD_READ事件中:
2.g_bProcState判断当前状态,_GAME_PROC时,把GameGate的发送过来的消息压入PacketQ队列中,再进行处理。
否则则调用OnMessageReceive(虚方法,根据g_bProcState状态,调用CloginProcess或者是CcharacterProcess的OnMessageReceive方法)。
3.CloginProcess:
调用OnSocketMessageRecieve处理返回情况。
如果服务器验证失败(SM_ID_NOTFOUND,SM_PASSWD_FAIL)消息,否则收到SM_PASSOK_SELECTSERVER消息(SelGate服务器列表消息)。
m_Progress=PRG_SERVER_SELE;进行下一步选择SelGate服务器操作。
4.m_xSelectSrv.OnButtonDown->CselectSrv.OnButtonUp->
g_xClientSocket.OnSelectServer(CM_SELECTSERVER),得到真正的IP地址。
调用OnSocketMessageRecieve处理返回的SM_SELECTSERVER_OK消息。
并且断开与loginSrv服务器连接。
g_xClientSocket.DisconnectToServer();设置状态为PRG_TO_SELECT_CHR状态。
角色选择处理:
1.WinMain消息循环处理:
g_xLoginProc.RenderScene(dwDelay)->RenderScroll->
SetNextProc调用
g_xClientSocket.m_pxDefProc=g_xMainWnd.m_pxDefProcess=&g_xChrSelProc;
g_xChrSelProc.Load();
g_bProcState=_CHAR_SEL_PROC;
2.g_xChrSelProc.Load();连接SelGate服务器(从LoginGate服务器得到IP地址)。
g_xClientSocket.OnQueryChar();查询用户角色信息,发送消息:
CM_QUERYCHR,设置状态为_CHAR_SEL_PROC,m_Progress=PRG_CHAR_SELE;在OnSocketMessageRecieve函数中接收到SelGate服务器发送的消息。
3.点击ChrStart按钮:
g_xChrSelProc.OnLButtonDown->CSelectChr:
:
OnButtonUp->
g_xClientSocket.OnSelChar->发送CM_SELCHR消息到SelGate服务器。
4.CClientSocket:
:
OnSocketMessage->CCharacterProcess:
:
OnMessageReceive
(SM_STARTPLAY)接受到SelGate服务器发送的GameGate服务器IP地址,并断开与SelGate服务器的连接。
m_xSelectChr.m_nRenderState=2;
5.WinMain消息循环处理:
g_xLoginProc.RenderScene->
m_xSelectChr.Render(nLoopTime);->CSelectChr:
:
Render(INT nLoopTime)->m_nRenderState=m_nRenderState+10;为12->CCharacterProcess:
:
RenderScene执行
m_Progress=PRG_SEL_TO_GAME;
m_Progress=PRG_PLAY_GAME;
SetNextProc();
6.SetNextProc();执行:
g_xGameProc.Load();g_bProcState=_GAME_PROC;进行游戏状态。
游戏逻辑处理:
1.客户端处理:
CGameProcess:
:
Load()初始化游戏环境,加载地图等操作,调用ConnectToServer(m_pxDefProc->OnConnectToServer)连接到GameGate游戏网关服务器(DBSrv处理后经SelGate服务器返回的GameGate服务器IP地址)。
CClientSocket->ConnectToServer调用connect时,由GameGate服务器发送GM_OPEN消息到GameSrv服务器。
WSAAsyncSelectI/O模型回调函数g_xClientSocket.OnSocketMessage。
然后由m_pxDefProc->OnConnectToServer()调用CGameProcess:
:
OnConnectToServer()函数,调用:
g_xClientSocket.SendRunLogin。
2.GameGate服务器ServerWorkerThread处理:
GameGate服务器ServerWorkerThread收到消息,ThreadFuncForMsg处理数据,生成MsgHdr结构,并设置
MsgHdr.nCode =0xAA55AA55;//数据标志
MsgHdr.wIdent =GM_DATA; //数据类型
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 传奇 源码 分析