118.网络游戏逆向分析与漏洞攻防-邮件系统数据分析-邮件管理的界面与功能设计

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!

如果看不懂、不知道现在做的什么,那就跟着做完看效果,代码看不懂是正常的,只要会抄就行,抄着抄着就能懂了

内容参考于:易道云信息技术研究院

上一个内容:117.结构数据的删除更新与重置

码云版本号:a6855e1ebe9f3aae8080c4200935a2539271ef50

代码下载地址,在 titan 目录下,文件名为:titan-邮件管理的界面与功能设计.zip

链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg

提取码:q9n5

--来自百度网盘超级会员V4的分享

HOOK引擎,文件名为:黑兔sdk升级版.zip

链接:https://pan.baidu.com/s/1IB-Zs6hi3yU8LC2f-8hIEw

提取码:78h8

--来自百度网盘超级会员V4的分享

以 117.结构数据的删除更新与重置 它的代码为基础进行修改

截止上一个内容为止,邮件相关的数据包(添加、删除、重置、修改)就全部拦截并转换成c++结构体,接下来开始给它创建ui界面并且把邮件的数据显示到ui界面中

首先添加一个dialog

给dialog添加一个类

类名CWndMail

它的属性

添加控件

添加变量

变量名 lstA

打开邮件,RecvLetterRec第11个属性

上图说11是打开邮件,但是它后面还有更新了第二个属性,第二个属性不是打开的原因,如下图,邮件并未打开2还是1,现在推测2是用来表示否是为系统邮件

有两个比较像是否系统邮件的

经过测试,它俩都不是,这个东西后面在搞

新加 CWndMail.cpp文件

// CWndMail.cpp: 实现文件
//#include "pch.h"
#include "CWndMail.h"
#include "afxdialogex.h"
#include "resource.h"
#include "CUI.h"
#include "extern_all.h"// CWndMail 对话框IMPLEMENT_DYNAMIC(CWndMail, CDialogEx)CWndMail::CWndMail(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_DIALOG2, pParent)
{}CWndMail::~CWndMail()
{
}void CWndMail::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_LIST3, lstA);
}BOOL CWndMail::OnInitDialog()
{CDialogEx::OnInitDialog();CUI* ui = (CUI*)Client;ui->SetListView(&lstA);lstA.InsertColumn(0, L"寄件人", 0, 130);lstA.InsertColumn(1, L"标题", 0, 130);lstA.InsertColumn(2, L"时间", 0, 130);return TRUE;
}BEGIN_MESSAGE_MAP(CWndMail, CDialogEx)ON_BN_CLICKED(IDC_BUTTON1, &CWndMail::OnBnClickedButton1)
END_MESSAGE_MAP()// CWndMail 消息处理程序void CWndMail::OnBnClickedButton1()
{lstA.DeleteAllItems();for (int i = 0; i < Client->Player.mailBox.size(); i++){CString txt;lstA.InsertItem(0, Client->Player.mailBox[i]->sender);txt.Format(L"%s", Client->Player.mailBox[i]->title);if(!Client->Player.mailBox[i]->value_14){CStringA titleA;titleA = Client->Player.mailBox[i]->title;txt = txtManger->ReadTextById(titleA.GetBuffer());}lstA.SetItemText(0, 1, txt);txt = Client->Player.mailBox[i]->szTime;lstA.SetItemText(0, 2, txt);}
}

新加 CWndMail.h文件

#pragma once
#include "afxdialogex.h"// CWndMail 对话框class CWndMail : public CDialogEx
{DECLARE_DYNAMIC(CWndMail)public:CWndMail(CWnd* pParent = nullptr);   // 标准构造函数virtual ~CWndMail();// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_DIALOG2 };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持virtual BOOL OnInitDialog();DECLARE_MESSAGE_MAP()
public:CListCtrl lstA;afx_msg void OnBnClickedButton1();
};

CWndSet.cpp文件的修改:修改了 OnInitDialog函数

// CWndSet.cpp: 实现文件
//#include "pch.h"
#include "CWndSet.h"
#include "afxdialogex.h"
#include "resource.h"
#include "extern_all.h"
#include "GameOBJECTDef.h"// CWndSet 对话框
extern CWndSet* _wndSet = nullptr;
IMPLEMENT_DYNAMIC(CWndSet, CDialogEx)CWndSet::CWndSet(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_PAGE_2, pParent)
{_wndSet = this;
}CWndSet::~CWndSet()
{
}void CWndSet::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BOOL CWndSet::OnInitDialog()
{CDialogEx::OnInitDialog();for (int i = 0; i < (unsigned)SETNAME::MAX; i++) {int x = i % 15;int y = i / 15;// 创建一个按钮,按钮样式是 BS_CHECKBOX,也就是一个复选框setButton[i].Create(txtName[i], BS_CHECKBOX | WS_CHILD, CRect(y*110+10, x*30+5, y*110+110, x*30+35), this, IDC_SETBASE + i);// 设置字体setButton[i].SetFont(GetFont());// 显示按钮setButton[i].ShowWindow(TRUE);}return TRUE;
}// i的值是 OnInitDialog函数里写的 setButton[i].Create 里的 IDC_SETBASE + i
void CWndSet::OnSet(UINT i) {int u = i - IDC_SETBASE;bool checked = setButton[u].GetCheck();setValue[u] = !checked;setButton[u].SetCheck(setValue[u]);float Speed;switch (u) {case (int)SETNAME::AddSpeed: {if (setValue[u])// 设置移动速度Speed = SetSpeed;elseSpeed = OldSpeed;Client->SetProperty(Client->Player.lId, INDEX_MoveSpeed, &Speed);break;}}
}
BEGIN_MESSAGE_MAP(CWndSet, CDialogEx)ON_CONTROL_RANGE(BN_CLICKED, IDC_SETBASE, IDC_SETBASE + (unsigned)SETNAME::MAX, OnSet)
END_MESSAGE_MAP()// CWndSet 消息处理程序

NetClient.cpp文件的修改:修改了 OnSvrStructInit函数

#include "pch.h"
#include "NetClient.h"
#include "extern_all.h"bool NetClient::login(const char* Id, const char* Pass)
{const int bufflen = sizeof(DATA_LOGIN) + 1;char buff[bufflen];DATA_LOGIN data;// 有些操作系统这样写会报错,因为内存不对齐,现在Windows下没事//PDATALOGIN _data = (PDATALOGIN)(buff + 1);// 这样写就能解决内存对齐问题PDATALOGIN _data =&data;int len = strlen(Id);memcpy(_data->Id, Id, len);len = strlen(Pass);memcpy(_data->Pass, Pass, len);memcpy(buff+1, _data, sizeof(DATA_LOGIN));buff[0] = I_LOGIN;return  NetSend(buff, sizeof(buff));}bool NetClient::DelRole(const wchar_t* rolename)
{PROLEDATA _role = GetRoleByName(rolename);if (_role == nullptr) {return false;}else {return DelRole(rolename, _role->name.lenth);}return false;
}bool NetClient::StartCreateRole()
{NET_CREATEROLE_START _data;return NetSend(&_data.op, _data.len);
}bool NetClient::SelectCamp(const char* _campname)
{NET_SEND_BUFF _buff;NET_SEND_CHOOSECAMP _data;_data.opcode.Set(SC_CHOOSECAMP);_data.camps.Set(_campname);/* sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}//性别 0 男 1 女
//
//阵营 1 艾森赫特 2 格兰蒂尔
//
//种族 1 布冯特人 3 格洛玛人 4 尤恩图人 6 喀什人
//
//职业 1 仲裁者 3秘法师 6 猎魔人 8 元素法师
//
//脸型 0 1 2 3
bool NetClient::CreateRole(wchar_t* name, double sex, double camp, double race, double occu, const char* photo, const char* infos, const char* txt, double faceShape)
{// rolecount > 4说明角色的数量够了if (rolecount > 4)return false;int index = 0;bool roleindex[5]{true, true, true, true, true };for (int i = 0; i < rolecount; i++) {roleindex[roles[i].index] = false;}for (int i = 0; i < 5; i++){if (roleindex[i]) {index = i;break;}}// wchar_t _name[] = L"am52111";NS_CREATEROLE_HEAD_BUFF _buff;CREATE_ROLE_DATAS _data;_data.sex.Set(sex);_data.camp.Set(camp);_data.face.Set(race);_data.occu.Set(occu);_data.faceSahpe.Set(faceShape);//_data.Photo.Set("gui\BG_team\TeamRole\Teamrole_zq_humF_001.PNG");_data.Photo.Set(photo);//_data.Infos.Set("Face,0;Hat,0;Eyes,0;Beard,0;Ears,0;Tail,0;Finger,0;Cloth,0;Pants,0;Gloves,0;Shoes,0;Trait,0;HairColor,0;SkinColor,0;SkinMtl,0;Tattoo,0;TattooColor,16777215;");_data.Infos.Set(infos);_data.Txt.Set(txt);short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;_buff.index = index;int lenth = wcslen(name) + 1;lenth = lenth * 2;memcpy(_buff.name, name, lenth);int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEHD_CREATEROLE_HEAD) - 3;return NetSend(&_buff.op, ilen);
}bool NetClient::SelectRole(const wchar_t* rolename)
{PROLEDATA roles = GetRoleByName(rolename);if (roles == nullptr)return false;NS_SELECTROLE _data;memcpy(_data.buff, roles->name.value(), roles->name.lenth);return NetSend((char*)&_data, sizeof(_data));
}bool NetClient::Fall()
{NET_SEND_BUFF _buff;FALL_DATA_STOP _data2;_data2.opcode.Set(SC_FALL_HEADER);_data2.Mode.Set(0x2);_data2.StartH.Set(Player.h);_data2.NextH.Set(Player.h - 12);_data2.EndH.Set(Player.h - 120);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data2) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data2.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);}void NetClient::Teleport(float x, float h, float y, float face)
{// 修正坐标//PAIM aim = GetAimByName(L"r");//if (aim == nullptr) {//	return;//}// 目的地坐标//float decX = aim->x;//float decH = aim->h;//float decY = aim->y;/*   float decX = 3843.776123f;float decH = 11.731983f;float decY = -2005.533813f;float face = 0.0f;*/union {unsigned nt = 0xFFC00000;float fNan;}v;/*这里的参数虽然都是无效值,但不见得就非要全部是无效值可能只设置x坐标就可以,可能值设置y坐标就可以,可能要设置x、y坐标就可以。。。现在全部设置成无效值了,如果游戏服务端有这个漏洞,我们角色的坐标就会全部设置成无效值,然后按照逻辑来讲下一次设置坐标的函数可以任意修改然后还可能有的游戏设置NaN不成功,这种的可以多试几个修改坐标或者其它数据的函数如果还都不行那就没办法了*///MoveWJump(v.fNan, v.fNan, v.fNan, v.fNan, v.fNan, v.fNan, v.fNan); // 可以把坐标设置成nan//MoveWalk(v.fNan, v.fNan, v.fNan, v.fNan, v.fNan, v.fNan, v.fNan); // 可以把坐标设置成nanMoveStop(v.fNan, v.fNan, v.fNan, v.fNan); // 可以把坐标设置成nanMoveStop(x, h, y, face);// 利用修正坐标数据包瞬移SetCoord(Player.lId, x, h, y, face);
}bool NetClient::MoveStop(float x, float h, float y, float face)
{NET_SEND_BUFF _buff;MOVE_DATA_STOP _data;_data.opcode.Set(SC_MOVE_HEADER);_data.Mode.Set(0x0);_data.Count.Set(4);_data.x.Set(x);_data.h.Set(h);_data.y.Set(y);_data.face.Set(face);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::MoveJump(float x, float h, float y, float face, float oldy, float xNext, float yNext)
{NET_SEND_BUFF _buff;MOVE_DATA_JUMP _data;_data.opcode.Set(SC_MOVE_HEADER);_data.Mode.Set(0x2);_data.Count.Set(9);_data.x.Set(x);_data.h.Set(h);_data.y.Set(y);_data.xNext.Set(xNext);_data.yNext.Set(yNext);_data.MoveSpeed.Set(Player.MoveSpeed);_data.JumpSpeed.Set(Player.JumpSpeed);_data.GSpeed.Set(0.0f);_data.face.Set(face);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::MoveWalk(float x, float h, float y, float face, float oldy, float xNext, float yNext)
{NET_SEND_BUFF _buff;MOVE_DATA_WALK _data;_data.opcode.Set(SC_MOVE_HEADER);_data.Mode.Set(0x1);_data.Count.Set(8);_data.x.Set(x);_data.h.Set(h);_data.y.Set(y);_data.xNext.Set(xNext);_data.yNext.Set(yNext);_data.MoveSpeed.Set(Player.MoveSpeed);_data.GSpeed.Set(0.0f);_data.face.Set(face);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::MoveWJump(float x, float h, float y, float face, float oldy, float xNext, float yNext)
{NET_SEND_BUFF _buff;MOVE_DATA_WJUMP _data;_data.opcode.Set(SC_MOVE_HEADER);_data.Mode.Set(0x3);_data.Count.Set(7);_data.x.Set(x);_data.h.Set(h);_data.y.Set(y);_data.xNext.Set(xNext);_data.yNext.Set(yNext);_data.MoveSpeed.Set(Player.MoveSpeed);_data.face.Set(face);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::UseSkill(const char* _skillName, float x, float h, float y, float face, float xTarget, float hTarget, float yTarget, int rInt1, int rInt2, int rInt3)
{NET_SEND_BUFF _buff;USESKILL_DATA _data;_data.opcode.Set(SC_USESKILL);_data.skillName.Set(_skillName);_data.x.Set(x);_data.h.Set(h);_data.y.Set(y);_data.xTarget.Set(xTarget);_data.hTarget.Set(hTarget);_data.yTarget.Set(yTarget);_data.un0.Set(rInt1);_data.un1.Set(rInt2);_data.un2.Set(rInt3);//_data.face.Set(face);_data.face.Set(0);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::UseItem(short BagIndex, short Index)
{NET_SEND_BUFF _buff;ITEM_USE_DATA _data;_data.opcode.Set(SC_ITEM_USE);_data.MainIndex.Set(BagIndex);_data.Index.Set(Index);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::ExChangeItem(short BagIndex, short Index, short tBagindex, short tIndex, bool IsEmpty)
{NET_SEND_BUFF _buff;ITEM_EXCHANGE_DATA _data;if(IsEmpty)_data.opcode.Set(SC_ITEM_EXCHANGE);else_data.opcode.Set(SC_ITEM_EXCHANGEEX);_data.MainIndex.Set(BagIndex);_data.Index.Set(Index);_data.TargetId.Set(tBagindex);_data.TargetIndex.Set(tIndex);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::DropItem(short BagIndex, short Index, short Amount)
{NET_SEND_BUFF _buff;ITEM_DROP_DATA _data;_data.opcode.Set(SC_ITEM_DROP);_data.MainIndex.Set(BagIndex);_data.Index.Set(Index);_data.Amount.Set(Amount);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::SplitItem(short BagIndex, short Index, short tBagindex, short tIndex, short Amount)
{NET_SEND_BUFF _buff;ITEM_SPLIT_DATA _data;_data.opcode.Set(SC_ITEM_SPLIT);_data.MainIndex.Set(BagIndex);_data.Index.Set(Index);_data.TargetId.Set(tBagindex);_data.TargetIndex.Set(tIndex);_data.TargetAmount.Set(Amount);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::Mount(short Index)
{NET_SEND_BUFF _buff;MOUNT_DATA _data;_data.opcode.Set(SC_MOUNT);_data.Index.Set(Index);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}PROLEDATA NetClient::GetRoleByName(const wchar_t* rolename)
{//PROLEDATA result = nullptr;for (int i = 0; i < rolecount; i++){// StrCmpW判断两个字符串是否相同// 比较时区分大小写,如果字符串相同返回0if (StrCmpW(roles[i].name.value(), rolename) == 0) {return &roles[i];}}return nullptr;
}bool NetClient::PickItem(short id, short Index)
{NET_SEND_BUFF _buff;ITEM_PICK_DATA _data;_data.opcode.Set(id);_data.Index.Set(Index);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::Talk(wchar_t* txt, int PdId, double un)
{NET_SEND_BUFF _buff;CHAT_PUBLIC _data;_data.opcode.Set(SC_CHAT);_data.ChartId.Set(PdId);_data.txt.Set(txt);_data.un.Set(un);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::TalkTo(wchar_t* name, wchar_t* txt, double un)
{NET_SEND_BUFF _buff;CHAT_PRIVATE _data;_data.opcode.Set(SC_CHAT);_data.ChartId.Set(3);_data.txt.Set(txt);_data.name.Set(name);_data.un.Set(un);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::HeartBeep()
{NET_SEND_BUFF _buff;HEART_BEEP _data;_data.opcode.Set(SC_BEEP);_data.tick.Set(3);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::BuyItem(int shopPage, int shopIndex, int itemIndex, int Amount)
{NET_SEND_BUFF _buff;ITEM_BUY_DATA _data;const char* shopId;auto _object = Client->GetGameOBJECTUnion((short)OBJECT_TYPE::Shop);if ((_object) && (_object->item)) {shopId = _object->item[0]->ShopID.GetBuffer();}else return false;_data.opcode.Set(SC_ITEM_SHOP);_data.opMode.Set(SC_ITEM_SHOP_BUY);_data.ShopId.Set(shopId);_data.ShopPage.Set(shopPage);_data.ShopIndex.Set(shopIndex);_data.Index.Set(itemIndex);_data.Amount.Set(Amount);_data.un1.Set(0);_data.un2.Set(0);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::HeartLoop()
{NET_SEND_BUFF _buff;HEART_LOOP _data;_data.opcode.Set(SC_LOOP);_data.tick.Set(GetTickCount64());_data.txt.Set("");/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::Backtoroles()
{// 返回角色NET_SEND_BUFF _buff;NSR_CHEAD _data;_data.opcode.Set(SC_REONLINE);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::SoldItem(int MainIndex, int Index, int Amount)
{NET_SEND_BUFF _buff;ITEM_SOLD_DATA _data;const char* shopId;auto _object = GetGameOBJECTUnion((short)OBJECT_TYPE::Shop);if ((_object) && (_object->item)) {shopId = _object->item[0]->ShopID.GetBuffer();}else return false;_data.opcode.Set(SC_ITEM_SHOP);_data.opMode.Set(SC_ITEM_SHOP_SOLD);_data.un1.Set(0);_data.ShopId.Set(shopId);_data.MainIndex.Set(MainIndex);_data.Index.Set(Index);_data.Amount.Set(Amount);/*sizeof(_data) / sizeof(EnCode)的原因NET_SEND_CHOOSECAMP结构体里面,没别 东西全是 EnCode 这个结构*/short count = sizeof(_data) / sizeof(EnCode);_buff.count = count;/*CodeMe函数给 _buff.buff里写数据参数的数据也就是给0A开头数据包里写,数据参数个数后面的内容然后返回值是写了多长的数据也就是给0A开头数据包里的数据参数个数后面的数据写了多长*/int ilen = _data.CodeMe(count, _buff.buff);ilen = ilen + sizeof(NET_SEND_HEAD) - 1;return NetSend(&_buff.op, ilen);
}bool NetClient::DelRole(const wchar_t* rolename, unsigned _len)
{DATA_DELROLE _data;_data.op = 0x06;_data.len = _len;memcpy(_data.buff, rolename, _len);return NetSend((char*)&_data, sizeof(DATA_DELROLE) - 1);
}PAIM NetClient::GetAimById(long long lId)
{if (Player.lId == 0)return &Player;// 我们玩家的数据未初始化其它的也不能初始化if (Player.lId == lId)return &Player;for (int i = 0; i < MAX_AIM; i++){if ((Aimlst[i] != nullptr) && (Aimlst[i]->lId == lId)) {return Aimlst[i];}}return CreateAim(lId);
}PAIM NetClient::CreateAim(long long lId)
{for (int i = 0; i < MAX_AIM; i++){if (Aimlst[i] == nullptr) {Aimlst[i] = new AIM();Aimlst[i]->lId = lId;return Aimlst[i];}else if (Aimlst[i]->Isfree) {Aimlst[i]->lId = lId;return Aimlst[i];}}return nullptr;
}void NetClient::RemoveAimById(long long lId)
{for (int i = 0; i < MAX_AIM; i++){if ((Aimlst[i] != nullptr) && (Aimlst[i]->lId == lId)) {// CString _txt;// _txt.Format(L"附近的 %s 消失", Aimlst[i]->Name);// AfxMessageBox(_txt);Aimlst[i]->Release();}}
}POBJECT_UNION NetClient::GetGameOBJECTUnion(short MainIndex)
{switch (MainIndex){case 1:return &Equip;case 2:return &Item;case 3:return &ItemEx;case 8:return &MountBag;case 0x28:return &Skill;case 0x3D:return &Shop;case 0x50:return &Pickup;}return nullptr;
}POBJECTBASE NetClient::GetGameOBJECT(short MainIndex, short Index)
{POBJECT_UNION _objectTable = GetGameOBJECTUnion(MainIndex);if (_objectTable) {return _objectTable->item[Index];}return nullptr;
}POBJECTBASE NetClient::ReSetGameOBJECT(short MainIndex, short max)
{max = max + 1;POBJECT_UNION _objectTable = GetGameOBJECTUnion(MainIndex);if (_objectTable) {_objectTable->Count = max;if (_objectTable->item) {if (max > _objectTable->MaxCount) {if (MainIndex == 0x28) {delete[] _objectTable->skill;delete[] _objectTable->skillAry;}else {delete[] _objectTable->item;delete[] _objectTable->itemAry;}}else {for (int i = 0; i < _objectTable->MaxCount; i++){_objectTable->item[i]->Isfree = true;}return  _objectTable->item[0];}}else   _objectTable->MaxCount = max;if (MainIndex == 0x28) {_objectTable->skill = new PSKILL[max];_objectTable->skillAry = new SKILL[max];for (int i = 0; i < max; i++) _objectTable->skill[i] = &_objectTable->skillAry[i];}else {_objectTable->item = new PITEM[max];_objectTable->itemAry = new ITEM[max];for (int i = 0; i < max; i++) _objectTable->item[i] = &_objectTable->itemAry[i];}return  _objectTable->item[0];}return nullptr;
}void NetClient::ExChangeOBJECT(short MainIndex, short IndexFrom, short IndexTo)
{POBJECT_UNION _objectTable = GetGameOBJECTUnion(MainIndex);if (_objectTable) {POBJECTBASE* _base = _objectTable->item;POBJECTBASE _tmp = _base[IndexFrom];_base[IndexFrom] = _base[IndexTo];_base[IndexTo] = _tmp;}
}void NetClient::DestoryOBJECT(short MainIndex, short Index)
{POBJECTBASE base = GetGameOBJECT(MainIndex, Index);if (base)base->Isfree = true;
}PAIM NetClient::GetAimByName(const wchar_t* name)
{for (int i = 0; i < MAX_AIM; i++){if ((Aimlst[i] != nullptr) && (!Aimlst[i]->Isfree) && (Aimlst[i]->Name == name)) {return Aimlst[i];}}return nullptr;
}// x,y是玩家的坐标,targetX,targetY是目标的坐标
float NetClient::GetFace(float x, float y, float targetX, float targetY)
{// 计算差值x = targetX - x;y = targetY - y;double pi = 3.14159265358979323846;double p = atan2(x, y); // atan2是计算三角形弧度atan2函数返回值-pi ~ pi,负的3.1415926...到正的3.1415926...// 如果x是负数atan2函数返回值必定是在三四象限里,也就是一个负πif (x < 0) {p = pi * 2 + p;}return p;
}void NetClient::FaceTo(const wchar_t* name)
{PAIM _aim = GetAimByName(name);if (_aim) {float _face = GetFace(Player.x, Player.y, _aim->x, _aim->y);MoveStop(Player.x, Player.h, Player.y, _face);}
}void NetClient::Init(PNetOperation _send, PNetOperation _recv)
{NetSend = _send;NetRecv = _recv;for (int i = 0; i < 0x100; i++) {SendProc[i] = &NetClient::DefaultProc;RecvProc[i] = &NetClient::DefaultProc;}// 注册登录数据包处理函数SendProc[I_LOGIN] = &NetClient::OnClientlogin;SendProc[I_CREATEROLE_START] = &NetClient::OnClientStartCreateRole;SendProc[I_DELROLE] = &NetClient::OnClientDelRole;SendProc[I_SEND_CUSTOM] = &NetClient::OnClientSendCustom;SendProc[I_CREATEROLE] = &NetClient::OnClientCreateRole;SendProc[I_SELECT_ROLE] = &NetClient::OnClientSelectRole;// 注册数据登录失败数据包处理函数RecvProc[S_TIPS] = &NetClient::OnSvrTips;RecvProc[S_LOGINOK] = &NetClient::OnSvrloginOk;RecvProc[S_CREATEROLE_START] = &NetClient::OnSvrStartCreateRole;RecvProc[S_NOTICE] = &NetClient::OnSverNotice;RecvProc[S_NOTICE_COM] = &NetClient::OnSverNotice;RecvProc[S_OBJECT] = &NetClient::OnSverObject;RecvProc[S_STRUCT] = &NetClient::OnSverStruct;RecvProc[S_OBJECT_INIT] = &NetClient::OnSvrObjectInit;RecvProc[S_OBJECT_INITEX] = &NetClient::OnSvrObjectInitEx;RecvProc[S_OBJECT_INITEX_UCOM] = &NetClient::OnSvrObjectInitEx;RecvProc[S_UPDATECORD] = &NetClient::OnSvrUpdateCord;RecvProc[S_UPDATEPRO] = &NetClient::OnSvrUpdateProperty;RecvProc[S_UPDATEPROMU] = &NetClient::OnSvrUpdatePropertyMu;RecvProc[S_UPDATEPROMU_COM] = &NetClient::OnSvrUpdatePropertyMu;RecvProc[S_OBJECT_REMOVE] = &NetClient::OnSvrRemoveObjectMu;RecvProc[S_UPDATECORDEX] = &NetClient::OnSvrUpdateCordEx;RecvProc[S_GAMEBASE] = &NetClient::OnSvrGameBase;RecvProc[S_GAMEBASE_RESET] = &NetClient::OnSvrGameBaseReset;RecvProc[S_GAMEBASE_EXCHANGE] = &NetClient::OnSvrGameBaseExChange;RecvProc[S_GAMEBASE_DROP] = &NetClient::OnSvrGameBaseDestroy;RecvProc[S_GAMEBASE_SET] = &NetClient::OnSvrGameBaseSet;RecvProc[S_STRUCT_INIT] = &NetClient::OnSvrStructInit;RecvProc[S_STRUCT_INITEX] = &NetClient::OnSvrStructInit;RecvProc[S_STRUCT_CLEAR] = &NetClient::OnSvrStructClear;RecvProc[S_STRUCT_DELETE] = &NetClient::OnSvrStructDelete;RecvProc[S_STRUCT_UPDATE] = &NetClient::OnSvrStructUpdate;
}bool NetClient::SetCoord(long long lId, float x, float h, float y, float face)
{NR_UPDATECOORD head;head.lId = lId;head.x = x;head.h = h;head.y = y;head.face = face;return NetRecv(&head.op, head.len);
}bool NetClient::SetProperty(long long lId, int ProType, void* value)
{NR_OBJECT_UPDATEPRO head;head.lId = lId;head.itype = ProType;int valueType = ObjectTable[ProType].type;int valueSize = data_desc[2][valueType].lenth;int bufflen = 14;switch (valueType){case 1:case 2:case 3:case 4:case 5:case 6:case 9:memcpy(head.buff, value, valueSize);bufflen = bufflen + valueSize;break;case 7:head.lenth = strlen((char*)value) + 1;memcpy(head.buffEnd, value, head.lenth);bufflen = bufflen + 4 + head.lenth;break;case 8:head.lenth = wcslen((wchar_t*)value) + 1;head.lenth = head.lenth + 2;memcpy(head.buffEnd, value, head.lenth);bufflen = bufflen + 4 + head.lenth;break;default:break;}return NetRecv(&head.op, bufflen);
}bool NetClient::OnDelRole(wchar_t* rolename, unsigned _len)
{// AfxMessageBox(rolename);return true;
}void NetClient::Onlogin(const char* Id, const char* Pass)
{/*const int bufflen = sizeof(DATA_LOGIN) + 1;char buff[bufflen];DATA_LOGIN data;// 有些操作系统这样写会报错,因为内存不对齐,现在Windows下没事//PDATALOGIN _data = (PDATALOGIN)(buff + 1);// 这样写就能解决内存对齐问题PDATALOGIN _data =&data;int len = strlen(Id);memcpy(_data->Id, Id, len);len = strlen(Pass);memcpy(_data->Pass, Pass, len);memcpy(buff+1, _data, sizeof(DATA_LOGIN));buff[0] = I_LOGIN;return  NetSend(buff, sizeof(buff));*/
}bool NetClient::OnStartCreateRole(int code)
{return true;
}bool NetClient::OnCreateRole(PNS_CREATEROLE _header, PCREATE_ROLE_DATAS _body)
{return true;
}bool NetClient::OnSendCustom(PNET_SEND_CHEAD _coder, char*& buffer, unsigned& len)
{switch (_coder->opcode.value()){case SC_CHOOSECAMP:return OnChooseCamp((PNS_CHOOSECAMP)_coder);case SC_CHAT:return OnChat((PCHAT_DATA)_coder);case SC_BEEP:return OnHeartBeep((PHEART_BEEP)_coder);case SC_LOOP:return OnHeartLoop((PHEART_LOOP)_coder);case SC_INITED:return OnInited();case SC_REONLINE://case SC_INIT_START://case SC_HAND://case SC_HAND_IN://    return false;case SC_MOVE_HEADER:return OnMove((PMOVE_DATA)_coder);case SC_FALL_HEADER:return OnFall((PFALL_DATA_START)_coder);case SC_INWATER:return false;case SC_USESKILL:return OnUseSkill((PUSESKILL)_coder);default:return true;}return true;
}bool NetClient::OnSelectRole(wchar_t* rolename)
{//AfxMessageBox(rolename);return true;
}bool NetClient::OnChooseCamp(PNS_CHOOSECAMP _coder)
{PNS_CHOOSECAMP _p = (PNS_CHOOSECAMP)_coder;return true;
}bool NetClient::OnChat(PCHAT_DATA _coder)
{switch (_coder->ChartId){case 3:// 私聊return OnChatPrivate((PCHAT_PRV)_coder);case 1:// 附近频道case 2:// 区域频道case 6:// 公会频道case 9:// 阵营频道case 21:// 喊话频道return OnChatPublic((PCHAT_PUB)_coder);break;}return true;
}bool NetClient::OnChatPublic(PCHAT_PUB _coder)
{return true;
}bool NetClient::OnChatPrivate(PCHAT_PRV _coder)
{return true;
}bool NetClient::OnHeartBeep(PHEART_BEEP _coder)
{return true; // 返回false会拦截81心跳包不给服务端发送
}bool NetClient::OnHeartLoop(PHEART_LOOP _coder)
{return true; // 返回false会拦截SC_LOOP心跳包不给服务端发送
}bool NetClient::OnMove(PMOVE_DATA _coder)
{switch (_coder->Mode){case 0:return OnMoveStop((PMOVE_DATA_STOP)_coder);case 1:return OnMoveWalk((PMOVE_DATA_WALK)_coder);case 2:return OnMoveJump((PMOVE_DATA_JUMP)_coder);case 3:return OnMoveWJump((PMOVE_DATA_WJUMP)_coder);}return false;
}// 移动中处理函数
bool NetClient::OnMoveWalk(PMOVE_DATA_WALK _coder)
{/*float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;MoveSpeed[0] = 5.0f;*//*if (HideMode) {float* f = (float*)_coder->h.oldPointer;f[0] = f[0] + 5;}*/return true;
}// 停止移动处理函数
bool NetClient::OnMoveStop(PMOVE_DATA_STOP _coder)
{/*  if (HideMode) {float* f = (float*)_coder->h.oldPointer;f[0] = f[0] + 5;}*/return true;
}// 跳跃处理函数
bool NetClient::OnMoveJump(PMOVE_DATA_JUMP _coder)
{//float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;//MoveSpeed[0] = 5.0f;//if(HideMode) {//    float* f = (float*)_coder->h.oldPointer;//    f[0] = f[0] + 5;//}return true;
}// 移动时跳跃
bool NetClient::OnMoveWJump(PMOVE_DATA_WJUMP _coder)
{/* float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;MoveSpeed[0] = 5.0f;*///if(HideMode) {//    float* f = (float*)_coder->h.oldPointer;//    f[0] = f[0] + 5;//}return true;
}bool NetClient::OnFall(PFALL_DATA_START _coder)
{return true;
}bool NetClient::OnSvrChat(PCHAT_PRV _coder)
{//AfxMessageBox(_coder->name);//AfxMessageBox(_coder->txt);//switch (_coder->ChartId)//{//case 3:// 私聊//    return OnChatPrivate((PCHAT_PRV)_coder);//case 1:// 附近频道//case 2:// 区域频道//case 6:// 公会频道//case 9:// 阵营频道//case 21:// 喊话频道//    return OnChatPublic((PCHAT_PUB)_coder);//    break;//}return true;
}bool NetClient::OnUseSkill(PUSESKILL _coder)
{// 无法x坐标无效,会无法释放技能/*float* f = (float*)_coder->x.oldPointer;f[0] = 0;*/return true;
}bool NetClient::OnInited()
{return true;
}bool NetClient::Tips(int code)
{
#ifdef  AnlyCString txt;if (code == 51001) {txt = L"登陆失败,易道云通行证不存在!";}else if (code == 51002) {txt = L"登录失败,密码错误!";}else if (code == 21101) {txt = L"人物重名!";}else if (code == 21109) {txt = L"名字过长或包含非法字符!";}else {txt.Format(L"未知登录错误:%d", code);}anly->SendData(TTYPE::I_LOG, 0, txt.GetBuffer(), (txt.GetLength() + 1)*2);
#endifreturn true;
}void NetClient::loginok(ROLE_DATA* _roles, int count)
{logined = true;if(roles) delete[] roles;roles = _roles;rolecount = count;
}bool NetClient::OnScrStartCreateRole(short code, wchar_t* _txt)
{return true;
}bool NetClient::OnSvrNotice(PNET_SEND_CHEAD _coder, int count, char*& buffer, unsigned& len)
{if (_coder->msgHeader == "chat") {return OnSvrChat((PCHAT_PRV)_coder);}return true;
}bool NetClient::OnRecvData(char*& buff, unsigned& len)
{
#ifdef  Anlyanly->SendData(TTYPE::I_RECV, buff[0], buff, len);
#endifreturn (this->*RecvProc[buff[0]])(buff, len);
}bool NetClient::OnSendData(char*& buff, unsigned& len)
{
#ifdef  Anlyanly->SendData(TTYPE::I_SEND, buff[0], buff, len);
#endifreturn (this->*SendProc[buff[0]])(buff, len);
}bool NetClient::OnConnect(char*& ip, unsigned& port)
{
#ifdef  Anly// 长度24的原因,它是宽字节要,一个文字要2个字节,一共是10个文字加上结尾的0是11个// 所以 11 乘以2,然后再加2 anly->SendData(TTYPE::I_LOG, 0, L"服务器正在连接。。。", 24);
#endifreturn true;
}// 默认的数据处理函数
bool NetClient::DefaultProc(char*&, unsigned&)
{return true;
}// 复制过来的内容
bool NetClient::OnClientlogin(char*& buff, unsigned& len)
{PDATALOGIN _data = (PDATALOGIN)(buff + 1);char* _id = _data->Id;_data = (PDATALOGIN)(buff + 1 + _data->lenId - 0x10);char* _pass = _data->Pass;Onlogin(_id, _pass);/* 修改账号密码len = sizeof(DATA_LOGIN) + 1;buff = new char[len];DATA_LOGIN data;PDATALOGIN _data = &data;buff[0] = 0x2;CStringA _id = "";// 补充账号CStringA _pass = "";// 补充密码memcpy(_data->Id, _id.GetBuffer(), _id.GetLength());memcpy(_data->Pass, _pass.GetBuffer(), _pass.GetLength());memcpy(buff + 1, _data, len - 1);*//* 监控登录数据PDATALOGIN _data = (PDATALOGIN)buff;CStringA _id = _data->Id;_data = (PDATALOGIN)(buff + _data->lenId - 0x10);CStringA _pass = _data->Pass;CStringA _tmp;// 请求登录 账号[% s]密码[% s] 这个内容别人在逆向的时候就会看到// 所以这种东西需要自己搞个编码来代替它_tmp.Format("请求登录 账号[%s]密码[%s]", _id, _pass);
#ifdef  Anlyanly->SendData(TTYPE::I_DIS, 1, _tmp.GetBuffer(), _tmp.GetAllocLength());
#endif*//*返回false,游戏无法发送数据包原因看调用此此函数的位置 OnSend 函数(if (SendDealProc[buff[0]]((buff + 1), len - 1)))*/return true;
}bool NetClient::OnClientStartCreateRole(char*& buff, unsigned& len)
{// 申请进入创建角色界面int* code = (int*)&buff[1];return OnStartCreateRole(code[0]);
}bool NetClient::OnClientCreateRole(char*& buff, unsigned& len) {PNS_CREATEROLE head = (PNS_CREATEROLE)(buff - 3);int icount = head->count;if (icount < 1)return true;char* buffStart = (char*)head + sizeof(NET_SEHD_CREATEROLE_HEAD);
#ifdef AnlyGameAnlyer->AnlyBuff(buffStart, buff + len, buff[0], 1);// 翻译解析约定数据
#endif // AnlyEnCode codes[sizeof(CREATE_ROLE_DATAS) / sizeof(EnCode)]{};int stDecode = 0;while (stDecode < icount) {codes[stDecode++] = buffStart;}/*OnCreateRole(head, (PCREATE_ROLE_DATAS)codes) 数据包传给虚函数如果想对发送创建角色数据包做些什么直接继承NetClient重写OnCreateRole函数既可以了*/return OnCreateRole(head, (PCREATE_ROLE_DATAS)codes);// 返回false屏蔽05开头的数据包,也就是创建角色发送的数据包
}bool NetClient::OnClientSendCustom(char*& buff, unsigned& len) {PNET_SEND_HEAD head = (PNET_SEND_HEAD)(buff - 1);int icount = head->count;if (icount < 1)return true;char* buffStart = (char*)head + sizeof(NET_SEND_HEAD);if (buffStart[0] != 0x02) {#ifdef  Anlyif (icount < MAX_SEND_COUNT)anly->SendData(TTYPE::I_DIS, I_SEND_CUSTOM, "SEND_CUSTOM MAX_SEND_COUNT 内存解码器空间不足", 46);anly->SendData(TTYPE::I_DIS, I_SEND_CUSTOM, "SEND_CUSTOM 发现异常数据", 25);
#endifreturn true;}#ifdef  AnlyGameAnlyer->AnlyBuff(buffStart, buff + len, buff[0], 1);
#endifint stDecode = 0;EnCode codes[MAX_SEND_COUNT]{};while (stDecode < icount) {codes[stDecode++] = buffStart;}/*OnSendCustom((PNET_SEND_CHEAD)codes, buff, len); 数据包传给虚函数如果想对发送数据的0A开头的据包做些什么直接继承NetClient重写OnSendCustom函数既可以了*/return OnSendCustom((PNET_SEND_CHEAD)codes, buff, len);}bool NetClient::OnClientSelectRole(char*& buff, unsigned& len) {PNS_SELECTROLE p = (PNS_SELECTROLE)buff;return OnSelectRole((wchar_t*)(p->buff));
}bool NetClient::OnClientDelRole(char*& buff, unsigned& len) {PDATADELROLE p = (PDATADELROLE)buff;return OnDelRole((wchar_t*)(p->buff), p->len);// 返回值改为false将拦截发送的删除角色数据包// 详情看注册 OnDelRole 函数的位置,Init函数// return true;
}// 接收数据截取区bool NetClient::OnSvrTips(char*& buff, unsigned& len) {int* code = (int*)&buff[1];return Tips(code[0]);
}bool NetClient::OnSvrloginOk(char*& buff, unsigned& len) {PDATALOGINOK _p = (PDATALOGINOK)&buff[1];ROLE_DATA* roleDatas = nullptr;if (_p->RoleCount > 0) {char* buffStart = buff + 1 + sizeof(DATA_LOGIN_OK);#ifdef AnlyGameAnlyer->AnlyBuff(buffStart, buff + len, buff[0]);
#endif // AnlyroleDatas = new ROLE_DATA[_p->RoleCount];for (int i = 0; i < _p->RoleCount; i++){roleDatas[i].byte.Init(buffStart, 0);roleDatas[i].index.Init(buffStart, 0);roleDatas[i].un1.Init(buffStart, 0);roleDatas[i].name.Init(buffStart, 0);roleDatas[i].infos.Init(buffStart, 0);roleDatas[i].un2.Init(buffStart, 0);roleDatas[i].un3.Init(buffStart, 0);}loginok(roleDatas, _p->RoleCount);}return true;
}bool NetClient::OnSverObject(char*& buff, unsigned& len) {PNR_HEAD head = (PNR_HEAD)(buff - 1);//head->count;if (ObjectTable) {delete[] ObjectTable;}if (ObjectTxt) {delete[] ObjectTxt;}ObjectTable = new OBJECT_DESC[head->count];ObjectTxt = new char[len];memcpy(ObjectTxt, buff, len);// 这里怕 buff 的内容被游戏释放掉,后面我们用的时候没法用,所以把buff的内容复制到我们的变量里char* buffStart = ObjectTxt + sizeof(NR_HEAD)-1;
//#ifdef Anly
//    CStringA szTxtA;
//    CStringA szTmp;
//#endif // Anly
//#ifdef Anly
//    szTmp.Format("[%X]%s:%d\r\n", i, ObjectTable[i].name, ObjectTable[i].type);
//    szTxtA += szTmp;
//#endif // Anly
//#ifdef  Anly
//    anly->SendData(TTYPE::I_DIS, S_OBJECT, szTxtA.GetBuffer(), szTxtA.GetAllocLength() + 1);
//#endif // Anlyfor (int i = 0; i < head->count; i++){ObjectTable[i].name = buffStart;buffStart = buffStart + strlen(ObjectTable[i].name) + 1;ObjectTable[i].type = buffStart[0];buffStart++;}#ifdef AnlyGameAnlyer->CreateObjectfiles(ObjectTable, head->count);
#endif // Anlyreturn true;
}
bool NetClient::OnSverStruct(char*& buff, unsigned& len) {PNR_HEAD head = (PNR_HEAD)(buff - 1);MaxStruct = head->count;if (StructTable) {delete[] StructTable;}if (StructTxt) {delete[] StructTxt;}StructTable = new STRUCT_DESC[head->count];StructTxt = new char[len];memcpy(StructTxt, buff, len);char* buffStart = StructTxt + sizeof(NR_HEAD) - 1;unsigned MaxOffSet = 0;for (int i = 0; i < head->count; i++){StructTable[i].name = buffStart;buffStart = buffStart + strlen(StructTable[i].name) + 1;short* icount = (short*)buffStart;StructTable[i].count = icount[0];buffStart = buffStart + 2;StructTable[i].buff = buffStart;buffStart = buffStart + icount[0];MaxOffSet += StructTable[i].count;}if (StructOffSet) delete[] StructOffSet;StructOffSet = new short[MaxOffSet];#ifdef AnlyGameAnlyer->CreateStructfile(StructTable, head->count);
#endif // Anly// 初始化偏移表InitStruct(StructTable, head->count, StructOffSet);return true;
}
bool NetClient::OnSvrObjectInit(char*& buff, unsigned& len)
{/*00 00 00 00 00 00 00 为了内存对齐补充了7个0,也就是 un1[6] 和 len28 opCD 48 00 01 62 A7 DE 04 PNR_OBJINIT:lIdC1 AA FB C3 PNR_OBJINIT:x;3D FF 22 41 PNR_OBJINIT:h;D7 0B 4A 44 PNR_OBJINIT:y;52 B8 06 40 PNR_OBJINIT:face;C1 AA FB C3 PNR_OBJINIT:tx;3D FF 22 41 PNR_OBJINIT:th;D7 0B 4A 44 PNR_OBJINIT:ty;52 B8 06 40 PNR_OBJINIT:tface;00 00 00 00 PNR_OBJINIT:un2[0]00 00 00 00 PNR_OBJINIT:un2[1]00 00 00 00 PNR_OBJINIT:un2[2]00 00 00 00 PNR_OBJINIT:un2[3]00 00 00 00 PNR_OBJINIT:un2[4]61 00       PNR_OBJINIT:icount;1B 00 (char*)head + sizeof(NR_OBNJECT_INIT) - 2;也就是指向到了 PNR_OBJINIT:type 这个位置0C 00 00 00 CA 4E 5A 66 53 62 01 80 4E 86 00 00 1D 00*/// 初始化对象PNR_OBJINIT head = (PNR_OBJINIT)(buff - 7);char* buffStart = (char*)head + sizeof(NR_OBNJECT_INIT) - 2;//int nStart = (int)&Player.lId;//int nEnd = (int)&Player.endclass;//memcpy(&Player.lId, &head->lId, nEnd - nStart);Player.SetHeadDatas(&head->lId);
#ifdef  AnlyGameAnlyer->AnlyData(buffStart, buff + len, head->icount, S_OBJECT_INIT, ObjectTable);
#endifint iProc = 0;while (iProc < head->icount){Player.UpdateData(buffStart);iProc++;}return true;
}
bool NetClient::OnSvrObjectInitEx(char*& buff, unsigned& len)
{// 初始化对象PNR_OBJINITEX head = (PNR_OBJINITEX)(buff - 5);char* buffStart;/*int nStart = (int)&Player.lId;int nEnd = (int)&Player.endclass;memcpy(&Player.lId, &head->lId, nEnd - nStart);*/int iObjectCount = 0;short objCount = head->obj_count; // 可以理解为一共有多少个接收的28数据while (iObjectCount < objCount) {PAIM _paim = GetAimById(head->lId);_paim->SetHeadDatas(&head->lId);buffStart = (char*)head + sizeof(NR_OBNJECT_INITEX) - 2;short refCount = head->icount; // 接收的28数据里的数据参数个数short iref = 0;
#ifdef  AnlyGameAnlyer->AnlyData(buffStart, buff + len, refCount, S_OBJECT_INITEX, ObjectTable);
#endifwhile (iref < refCount) {_paim->UpdateData(buffStart);iref++;}head = (PNR_OBJINITEX)(buffStart - 8);iObjectCount++;}return true;
}
bool NetClient::OnSvrUpdateCord(char*& buff, unsigned& len)
{/*00 00 00 00 00 head21 02 00 CD 14 00 01 CD 14 00 00 第一个坐标数据6D BF 54 43 A6 FA C7 3F 8C 52 A9 C1 CB 30 06 40 00 00 00 00 DB 0F C9 41 00 00 00 00 00 00 00 00 01 00 00 00 StateCD 14 00 01 CD 14 00 00 第二个坐标数据61 41 5B 43 A6 FA C7 3F C5 8A C7 C1 CB 30 06 40 9A 99 99 3E DB 0F C9 40 00 00 00 00 00 00 00 00 01 00 00 00 */// 初始化对象PNR_OBJINITEX head = (PNR_OBJINITEX)(buff - 5);/*int nStart = (int)&Player.lId;int nEnd = (int)&Player.endclass;memcpy(&Player.lId, &head->lId, nEnd - nStart);*/int iObjectCount = 0;short objCount = head->obj_count; // 可以理解为一共有多少个接收的28数据while (iObjectCount < objCount) {PAIM _paim = GetAimById(head->lId);_paim->SetHeadDatas(&head->lId);CStringA txtA;txtA.Format("x:%f h:%f y:%f", head->x, head->h, head->y);
#ifdef  Anlyanly->SendData(TTYPE::I_DIS, S_UPDATECORD, txtA.GetBuffer(), txtA.GetAllocLength() + 1);
#endifhead = (PNR_OBJINITEX)((char*)&head->State - 4);iObjectCount++;}return true;
}
bool NetClient::OnSvrUpdateProperty(char*& buff, unsigned& len)
{// 初始化对象PNR_OBJECT_UP head = (PNR_OBJECT_UP)(buff - 6);PGAMEOBJ _object = nullptr;char* buffStart = (char*)&head->itype;short refcount = head->icount;int iref = 0;
#ifdef  AnlyGameAnlyer->AnlyData(buffStart, buff + len, refcount, S_UPDATEPRO, ObjectTable);
#endifif (head->MsgId ) {_object = GetGameOBJECT(head->Index[0], head->Index[1]);}else {_object = GetAimById(head->lId);}while ((iref < refcount)&&(_object)) {_object->UpdateData(buffStart);iref++;}return true;
}
bool NetClient::OnSvrUpdatePropertyMu(char*& buff, unsigned& len)
{// 初始化对象PNR_OBJECT_UPMU head = (PNR_OBJECT_UPMU)(buff - 5);int iobjCount = 0;short objCount = head->objCount; // 可以理解为一共有多少个接收的28数据char* buffStart;/*数据包是下方的样子,2D 01 00 objCount9B 49 00 01 D5 8C 98 05  GetAimById(head->lId);02 00 25 00 (char*)&head->itype18 00 00 00 29 00 BA 01 00 00 while (iobjCount < objCount) 里获取的是9B 49 00 01 D5 8C 98 0502 0025 00 18 00 00 0029 00 BA 01 00 00 这一块数据while (iref++ < refCount) 里获取的是25 00 18 00 00 00(PNR_OBJECT_UPMU)(buffStart - 8); 移动到下一个9B 49 00 01 D5 8C 98 05  GetAimById(head->lId);02 0025 00 (char*)&head->itype18 00 00 0029 00 BA 01 00 00 这个数据*/while (iobjCount < objCount) {PAIM _paim = GetAimById(head->lId);buffStart = (char*)&head->itype;short refCount = head->icount; // 接收的28数据里的数据参数个数short iref = 0;#ifdef  AnlyGameAnlyer->AnlyData(buffStart, buff + len, refCount, S_UPDATEPROMU, ObjectTable);
#endifwhile (iref++ < refCount) {_paim->UpdateData(buffStart);}head = (PNR_OBJECT_UPMU)(buffStart - 8);iobjCount++;}return true;
}
bool NetClient::OnSvrRemoveObjectMu(char*& buff, unsigned& len)
{// 初始化对象PNR_OBJECT_REMOVEMU head = nullptr;head = (PNR_OBJECT_REMOVEMU)(buff - &head->op);int iobjCount = head->objCount;for (int i = 0; i < iobjCount; i++){RemoveAimById(head->lId[i]);}return true;
}/*1F87 44 00 01 7F B0 D6 05FE AD DE C36C F5 46 4207 FD 36 C490 D9 9C 40
*/
bool NetClient::OnSvrUpdateCordEx(char*& buff, unsigned& len)
{// 初始化对象PNR_UPDATECOORD head = nullptr;head = (PNR_UPDATECOORD)(buff - &head->op);PAIM aim = GetAimById(head->lId);if (aim) {return aim->SetHeadCord(&head->lId);}return true;
}
bool NetClient::OnSvrGameBase(char*& buff, unsigned& len)
{// 初始化对象PNR_GAMEBASE head = nullptr; head = (PNR_GAMEBASE)(buff - &head->op);char* buffStart = (char*)head + sizeof(NR_GAMEBASE);//int nStart = (int)&Player.lId;//int nEnd = (int)&Player.endclass;//memcpy(&Player.lId, &head->lId, nEnd - nStart);//Player.SetHeadDatas(&head->lId);
#ifdef  AnlyCStringA szTxt;szTxt.Format("%X %X", head->type, head->index);anly->SendData(TTYPE::I_DIS, S_GAMEBASE, szTxt.GetBuffer(), szTxt.GetAllocLength() + 1);GameAnlyer->AnlyData(buffStart, buff + len, head->count, S_GAMEBASE, ObjectTable);
#endifPOBJECTBASE object = GetGameOBJECT(head->type, head->index);if (object == nullptr)return true;object->MainIndex = head->type;object->Index = head->index;int iProc = 0;while (iProc < head->count){object->UpdateData(buffStart);iProc++;}return true;
}
bool NetClient::OnSvrGameBaseReset(char*& buff, unsigned& len)
{PNR_GAMEBASE_RESET head = nullptr;head = (PNR_GAMEBASE_RESET)(buff - &head->op);POBJECTBASE object = ReSetGameOBJECT(head->type, head->max);if (object) {char* buffStart = (char*)head + sizeof(NR_GAMEBASE);int iProc = 0;while (iProc < head->count){object->UpdateData(buffStart);iProc++;}}return true;
}
bool NetClient::OnSvrGameBaseExChange(char*& buff, unsigned& len)
{PNR_GAMEBASE_EXCHANGE head = nullptr;head = (PNR_GAMEBASE_EXCHANGE)(buff - &head->op);ExChangeOBJECT(head->MainIndex, head->IndexFrom, head->IndexTo);return true;
}
bool NetClient::OnSvrGameBaseDestroy(char*& buff, unsigned& len)
{PNR_GAMEBASE_DROP head = nullptr;head = (PNR_GAMEBASE_DROP)(buff - &head->op);DestoryOBJECT(head->MainIndex, head->Index);return true;
}
bool NetClient::OnSvrGameBaseSet(char*& buff, unsigned& len)
{PNR_GAMEBASE_SET head = nullptr;head = (PNR_GAMEBASE_SET)(buff - &head->op);POBJECTBASE object = ReSetGameOBJECT(head->MainIndex, 0);if (object) {char* buffStart = head->buff;int iProc = 0;while (iProc < head->count){object->UpdateData(buffStart);iProc++;}}return true;
}
bool NetClient::OnSvrStructInit(char*& buff, unsigned& len)
{PNR_STRUCT_INIT head = nullptr;head = (PNR_STRUCT_INIT)(buff - &head->op);#ifdef AnlyGameAnlyer->AnlyStruct(head, buff + len, S_STRUCT_INIT, StructTable);
#endifif (head->optype) {return true;}else {PAIM aim = GetAimById(head->lId);if (aim->CreateStruct(head->StructIndex, head->Start, head->Count)) {char* buffStart = head->buff;int iProc = 0;while (iProc < head->Count){UpdateStruct(aim, head->StructIndex, head->Start + iProc, buffStart);iProc++;}}else return true;}}
bool NetClient::UpdateStruct(PAIM aim, short structIndex, short index, char*& buff)
{void* base = aim->GetStruct(structIndex, index);if (!base) return false;short icount = StructTable[structIndex].count;short iProc = 0;while (iProc < icount) {short type = StructTable[structIndex].buff[iProc];switch (type){case 1:UpdateStructByte(base, aim, structIndex, iProc, buff);break;case 2:UpdateStructShort(base, aim, structIndex, iProc, buff);break;case 3:UpdateStructInt(base, aim, structIndex, iProc, buff);break;case 5:UpdateStructfloat(base, aim, structIndex, iProc, buff);break;case 6:UpdateStructDouble(base, aim, structIndex, iProc, buff);break;case 7:UpdateStructAscii(base, aim, structIndex, iProc, buff);break;case 8:UpdateStructUnicode(base, aim, structIndex, iProc, buff);break;case 4:case 9:UpdateStructInt64(base, aim, structIndex, iProc, buff);break;default:return false;}iProc++;}return true;
}
bool NetClient::OnSvrStructClear(char*& buff, unsigned& len)
{PNR_STRUCT_INIT head = nullptr;head = (PNR_STRUCT_INIT)(buff - &head->op);if (head->optype) {return true;}else {PAIM aim = GetAimById(head->lId);aim->DeleteStruct(head->StructIndex);}return true;
}
bool NetClient::OnSvrStructDelete(char*& buff, unsigned& len)
{PNR_STRUCT_INIT head = nullptr;head = (PNR_STRUCT_INIT)(buff - &head->op);if (head->optype) {return true;}else {PAIM aim = GetAimById(head->lId);aim->DeleteStruct(head->StructIndex, head->DelIndex);}return true;
}
bool NetClient::OnSvrStructUpdate(char*& buff, unsigned& len)
{PNR_STRUCT_UPDATE head = nullptr;head = (PNR_STRUCT_UPDATE)(buff - &head->op);if (head->optype) {return true;}else {
#ifdef AnlyGameAnlyer->AnlyStruct(head, buff + len, S_STRUCT_UPDATE, StructTable);
#endifPAIM aim = GetAimById(head->lId);char* buffStart = head->buff;UpdateStruct(aim, head->StructIndex, buffStart, head->Count);}return true;
}
bool NetClient::UpdateStructByte(void* base, PAIM aim, short structIndex, short index, char*& buff)
{char* writer = (char*)((char*)base + StructTable[structIndex].offset[index]);writer[0] = buff[0];buff = buff + sizeof(char);return true;
}
bool NetClient::UpdateStructShort(void* base, PAIM aim, short structIndex, short index, char*& buff)
{short* writer = (short*)((char*)base + StructTable[structIndex].offset[index]);short* wtstream = (short*)buff;writer[0] = wtstream[0];buff = buff + sizeof(short);return true;
}
bool NetClient::UpdateStructInt(void* base, PAIM aim, short structIndex, short index, char*& buff)
{int* writer = (int*)((char*)base + StructTable[structIndex].offset[index]);int* wtstream = (int*)buff;writer[0] = wtstream[0];buff = buff + sizeof(int);return true;
}
bool NetClient::UpdateStructInt64(void* base, PAIM aim, short structIndex, short index, char*& buff)
{long long* writer = (long long*)((char*)base + StructTable[structIndex].offset[index]);long long* wtstream = (long long*)buff;writer[0] = wtstream[0];buff = buff + sizeof(long long);return true;
}
bool NetClient::UpdateStructfloat(void* base, PAIM aim, short structIndex, short index, char*& buff)
{float* writer = (float*)((char*)base + StructTable[structIndex].offset[index]);float* wtstream = (float*)buff;writer[0] = wtstream[0];buff = buff + sizeof(float);return true;
}
bool NetClient::UpdateStruct(PAIM aim, short structIndex, char*& buff, short count)
{short iProc = 0;while (iProc < count) {short* pindex = (short*)buff;buff = buff + 2;char* sIndex = buff;void* base = aim->GetStruct(structIndex, pindex[0]);if (!base)return true;short type = StructTable[structIndex].buff[sIndex[0]];buff = buff + 1;switch (type){case 1:UpdateStructByte(base, aim, structIndex, sIndex[0], buff);break;case 2:UpdateStructShort(base, aim, structIndex, sIndex[0], buff);break;case 3:UpdateStructInt(base, aim, structIndex, sIndex[0], buff);break;case 5:UpdateStructfloat(base, aim, structIndex, sIndex[0], buff);break;case 6:UpdateStructDouble(base, aim, structIndex, sIndex[0], buff);break;case 7:UpdateStructAscii(base, aim, structIndex, sIndex[0], buff);break;case 8:UpdateStructUnicode(base, aim, structIndex, sIndex[0], buff);break;case 4:case 9:UpdateStructInt64(base, aim, structIndex, sIndex[0], buff);break;default:return false;}iProc++;}return true;
}
bool NetClient::UpdateStructDouble(void* base, PAIM aim, short structIndex, short index, char*& buff)
{double* writer = (double*)((char*)base + StructTable[structIndex].offset[index]);double* wtstream = (double*)buff;writer[0] = wtstream[0];buff = buff + sizeof(double);return true;
}
bool NetClient::UpdateStructAscii(void* base, PAIM aim, short structIndex, short index, char*& buff)
{GASCII* writer = (GASCII*)((char*)base + StructTable[structIndex].offset[index]);int* Plen = (int*)buff;// 如果是字符串,第一个字节是一个int类型,用来表示字符串的长度buff = buff + 4;writer[0] = buff;buff = buff + Plen[0];return true;
}
bool NetClient::UpdateStructUnicode(void* base, PAIM aim, short structIndex, short index, char*& buff)
{GUNICODE* writer = (GUNICODE*)((char*)base + StructTable[structIndex].offset[index]);int* Plen = (int*)buff;// 如果是字符串,第一个字节是一个int类型,用来表示字符串的长度buff = buff + 4;writer[0] = (wchar_t*)buff;// 如果是宽字节需要强制转换,不然会乱码buff = buff + Plen[0];//CString txt;//txt.Format(L"%s %d", writer[0], StructTable[structIndex].offset[index]);//AfxMessageBox(txt);return true;
}
/*OnSverrNotice函数处理的数据包格式如下1E 06 0006 11 00 00 00 70 6C 61 79 5F 70 6F 69 6E 74 5F 73 6F 75 6E 64 0006 01 00 00 00 0004 2C 92 87 C504 FA 03 BF 4204 33 14 BD 4502 00 00 00 001E 06 00 是 PNR_NOTICE_HEAD06 11 00 00 00 70 6C 61 79 5F 70 6F 69 6E 74 5F 73 6F 75 6E 64 00是一个EnCode06 01 00 00 00 00是一个EnCode04 2C 92 87 C5是一个EnCode04 FA 03 BF 42是一个EnCode04 33 14 BD 45是一个EnCode02 00 00 00 00是一个EnCode
*/
bool NetClient::OnSverNotice(char*& buff, unsigned& len) {PNR_NOTICE_HEAD head = (PNR_NOTICE_HEAD)(buff - 1);int icount = head->count;char* buffStart = (char*)head + sizeof(NR_NOTICE_HEAD);if (icount < 1) {return true;}if (icount > MAX_RECV_COUNT) {
#ifdef  Anlyanly->SendData(TTYPE::I_DIS, S_NOTICE, "S_NOTICE 解码器内存不足", 24);
#endifreturn true;}#ifdef  AnlyGameAnlyer->AnlyBuff(buffStart, buff + len, buff[0], 1);
#endifint stDecode = 0;EnCode codes[MAX_RECV_COUNT]{};while (stDecode < icount) {codes[stDecode++] = buffStart;}return OnSvrNotice((PNET_SEND_CHEAD)codes, icount, buff, len);
}bool NetClient::OnSvrStartCreateRole(char*& buff, unsigned& len) {short* _st = (short*)&buff[1];wchar_t* _txt = (wchar_t*)&buff[3];
#ifdef  AnlyCString txt;CStringA txtA;txt.Format(L"code:%d\r\n%s", _st[0], _txt);txtA = txt;//AfxMessageBox(txtA);anly->SendData(TTYPE::I_DIS, S_CREATEROLE_START, txtA.GetBuffer(), txt.GetAllocLength() + 1);
#endif/*OnSendCustom((PNET_SEND_CHEAD)codes, buff, len); 数据包传给虚函数如果想对0A开头的据包做些什么直接继承NetClient重写OnSendCustom函数既可以了*/return OnScrStartCreateRole(_st[0], _txt);
}

GameAnly.cpp文件的修改:修改了 AnlyStruct函数

#include "pch.h"
#include "GameAnly.h"
#include <iostream>
#include <fstream>#ifdef Anly
// 它会生成一个结构体,详情看效果图
void GameAnly::AnlyBuff(char* start, char* end, int MsgId, char index)
{CStringA txt;CStringA tmp;CString utmp;EnCode _coder;GBYTE* _bytecoder;GSHORT* _shortcoder;GINT* _intcoder;GFLOAT* _floatcoder;GDOUBLE* _doublecoder;GCHAR* _asccoder;GUTF16* _utfcoder;GINT64* _int64coder;while (start < end) {_coder.Init(start, index);CStringA _opname = data_desc[_coder.index][_coder.op].name;// _opname.MakeLower()是变为小写字母,会影响 _opname它的值// 所以又写了一边 data_desc[_coder.index][_coder.op].nametmp.Format("%s %s;//", data_desc[_coder.index][_coder.op].name, _opname.MakeLower().GetBuffer());txt = txt + tmp;if (_coder.index == 0) {switch (_coder.op){case 1:_shortcoder = (GSHORT*)&_coder;tmp.Format("%d\r\n", _shortcoder->value());txt = txt + tmp;break;case 2:_intcoder = (GINT*)&_coder;tmp.Format("%d\r\n", _intcoder->value());txt = txt + tmp;break;case 4:_floatcoder = (GFLOAT*)&_coder;tmp.Format("%f\r\n", _floatcoder->value());txt = txt + tmp;break;case 6:_bytecoder = (GBYTE*)&_coder;tmp.Format("%d\r\n", _bytecoder->value());txt = txt + tmp;break;case 7:_utfcoder = (GUTF16*)&_coder;utmp.Format(L"[%s]\r\n", _utfcoder->value());tmp = utmp;txt = txt + tmp;break;// 5号之前分析的忘记截图了,现在找不到它的数据包了,如果后面再见到05的时候再详细补充说明// 之前的分析05就是double类型case 5:_doublecoder = (GDOUBLE*)&_coder;tmp.Format("%lf\r\n", _doublecoder->value());txt = txt + tmp;break;case 8:case 3:_int64coder = (GINT64*)&_coder;tmp.Format("%lld\r\n", _int64coder->value());txt = txt + tmp;break;default:break;}}if (_coder.index == 1) {switch (_coder.op){case 1:_shortcoder = (GSHORT*)&_coder;tmp.Format("%d\r\n", _shortcoder->value());txt = txt + tmp;break;case 2:_intcoder = (GINT*)&_coder;tmp.Format("%d\r\n", _intcoder->value());txt = txt + tmp;break;case 4:_floatcoder = (GFLOAT*)&_coder;tmp.Format("%f\r\n", _floatcoder->value());txt = txt + tmp;break;case 6:_asccoder = (GCHAR*)&_coder;tmp.Format("%s\r\n", _asccoder->value());txt = txt + tmp;break;case 7:_utfcoder = (GUTF16*)&_coder;utmp.Format(L"[%s]\r\n", _utfcoder->value());tmp = utmp;txt = txt + tmp;break;case 5:_doublecoder = (GDOUBLE*)&_coder;tmp.Format("%lf\r\n", _doublecoder->value());txt = txt + tmp;break;case 8:case 3:_int64coder = (GINT64*)&_coder;tmp.Format("%lld\r\n", _int64coder->value());txt = txt + tmp;break;default:break;}}}anly->SendData(TTYPE::I_DIS, MsgId, txt.GetBuffer(), txt.GetAllocLength() + 1);
}
void GameAnly::AnlyData(char* start, char* end, int count, int MsgId, POBJ_DESC desc)
{int iProc = 0;int value;long long llvalue;float fvalue;double dbval;CStringA szTmp, _tmp, szTxt, _tmp1;CString wTmp;while ((iProc < count) && (start <end)) {short* index = (short*)start;int type = desc[index[0]].type;char* name = desc[index[0]].name;switch (type){case 0:AfxMessageBox(L"0号信息!"); break;case 1:value = ToChar(start);szTmp.Format("%s = %d", name, value);break;case 2:value = ToShort(start);szTmp.Format("%s = %d", name, value);break;case 3:value = ToInt(start);szTmp.Format("%s = %d", name, value);break;case 4:llvalue = ToLLong(start);szTmp.Format("%s = %lld", name, llvalue);break;case 5:fvalue = ToFloat(start);szTmp.Format("%s = %f", name, fvalue);break;case 6:dbval = ToDouble(start);szTmp.Format("%s = %lf", name, dbval);break;case 7:_tmp = ToAscii(start);_tmp1 = name;if (_tmp1 == "ConfigID") {_tmp = "desc_" + _tmp + "_1";wTmp = txtManger->ReadTextById(_tmp);_tmp1 = wTmp;}szTmp.Format("%s = %s\r\ntext=%s", name, _tmp.GetBuffer(), _tmp1.GetBuffer());break;case 8:wTmp = ToUniode(start);_tmp = wTmp;szTmp.Format("%s = %s", name, _tmp.GetBuffer());break;case 9:llvalue = ToLLong(start);szTmp.Format("%s = %llX", name, llvalue);break;default:break;}szTxt = szTxt + szTmp + "\r\n";iProc++;}anly->SendData(TTYPE::I_DIS, MsgId, szTxt.GetBuffer(), szTxt.GetAllocLength() + 1);//CStringA tmpA;//CStringA szTxt, szTmp;//szTmp.Format("id:%lld\r\n", head->lId);//szTxt = szTxt + szTmp;//szTmp.Format("x:%f h:%f y:%f\r\n", head->x, head->h, head->y);//szTxt = szTxt + szTmp;//char* buffStart = (char*)head + sizeof(NR_OBNJECT_INIT) - 2;//int icount = head->icount;//int iProc = 0;//while (iProc < icount) {//    short* type = (short*)buffStart;//    char* _name = ObjectTable[type[0]].name;//    int _type = ObjectTable[type[0]].type;//    char* _byte;//    short* _short;//    int* _int;//    float* _float;//    long long* _llong;//    double* _double;//    int lenth;//    CString _txt;//    /*//        1B 00 type[0] buffStart + 2;//        0C 00 00 00 CA 4E 5A 66 53 62 01 80 4E 86 00 00//        1D 00 type[0]//        00 00 48 42 buffStart + 2;//        01 00 type[0]//        02 buffStart + 2;//        02 00 type[0]//        01 buffStart + 2;//        03 00 2E 00 00 00 67 75 69 5C 42 47 5F 74 65 61 6D 5C 54 65 61 6D 52 6F 6C 65 5C 54 65 61 6D 72 6F 6C 65 5F 7A 71 5F 68 75 6D 46 5F 30 30 31 2E 50 4E 47 00//        04 00 01 00 00 00//        05 00 01 00 00 00//        06 00 01 00 00 00//        07 00 01 00 00 00//        08 00 00 B1 9E 00//    *///    buffStart = buffStart + 2;//    switch (_type)//    {//    case 0://        AfxMessageBox(L"0号信息!"); break;//    case 1://        _byte = buffStart;//        szTmp.Format("%s = %d", _name, _byte[0]);//        buffStart = buffStart + 1;//        break;//    case 2://        _short = (short*)buffStart;//        szTmp.Format("%s = %d", _name, _short[0]);//        buffStart = buffStart + 2;//        break;//    case 3://        _int = (int*)buffStart;//        szTmp.Format("%s = %d", _name, _int[0]);//        buffStart = buffStart + 4;//        break;//    case 4://        _llong = (long long*)buffStart;//        szTmp.Format("%s = %lld", _name, _llong[0]);//        buffStart = buffStart + 8;//        break;//    case 5://        _float = (float*)buffStart;//        szTmp.Format("%s = %f", _name, _float[0]);//        buffStart = buffStart + 4;//        break;//    case 6://        _double = (double*)buffStart;//        szTmp.Format("%s = %lf", _name, _double[0]);//        buffStart = buffStart + 8;//        break;//    case 7://        _int = (int*)buffStart;//        lenth = _int[0];//        // szTmp = buffStart + 4;//        szTmp.Format("%s = %s", _name, buffStart + 4);//        buffStart = buffStart + 4 + lenth;//        break;//    case 8://        _int = (int*)buffStart;//        lenth = _int[0];//        _txt = (wchar_t*)(buffStart + 4);//        tmpA = _txt;//        szTmp.Format("%s = %s", _name, tmpA);//        buffStart = buffStart + 4 + lenth;//        break;//    case 9:MessageBoxA(0, buffStart, buffStart, MB_OK); return true;//    default://        break;//    }//    szTxt = szTxt + szTmp + "\r\n";//    iProc++;//}//anly->SendData(TTYPE::I_DIS, S_OBJECT_INIT, szTxt.GetBuffer(), szTxt.GetAllocLength() + 1);
}
void GameAnly::AnlyStruct(PNR_STRUCT_INIT start, char* end, int MsgId, PSTRUCT_DESC desc)
{PNR_STRUCT_INIT head = start;char* buffstart = head->buff;int value;long long llvalue;float fvalue;double dbval;CStringA szTmp, _tmp, szTxt, _tmp1;CString wTmp;int iProc = 0;while (iProc < head->Count){CStringA txtOut;txtOut.Format("%s[%d]\r\n", desc[head->StructIndex].name, iProc);int icount = 0;while (icount < desc[head->StructIndex].count) {buffstart = buffstart - 2;switch (desc[head->StructIndex].buff[icount]){case 0:AfxMessageBox(L"0号信息!"); break;case 1:value = ToChar(buffstart);szTmp.Format("value_%d = %d", icount, value);break;case 2:value = ToShort(buffstart);szTmp.Format("value_%d = %d", icount, value);break;case 3:value = ToInt(buffstart);szTmp.Format("value_%d = %d", icount, value);break;case 4:llvalue = ToLLong(buffstart);szTmp.Format("value_%d = %lld", icount, llvalue);break;case 5:fvalue = ToFloat(buffstart);szTmp.Format("value_%ds = %f", icount, fvalue);break;case 6:dbval = ToDouble(buffstart);szTmp.Format("value_%d = %lf", icount, dbval);break;case 7:_tmp = ToAscii(buffstart);szTmp.Format("value_%d = %s", icount, _tmp.GetBuffer());break;case 8:wTmp = ToUniode(buffstart);_tmp = wTmp;szTmp.Format("value_%d = %s", icount, _tmp.GetBuffer());break;case 9:llvalue = ToLLong(buffstart);szTmp.Format("value_%d = %llX", icount, llvalue);break;default:break;}txtOut = txtOut + szTmp + "\r\n";icount++;}anly->SendData(TTYPE::I_DIS, MsgId, txtOut.GetBuffer(), txtOut.GetAllocLength() + 1);iProc++;}}
void GameAnly::AnlyStruct(PNR_STRUCT_UPDATE start, char* end, int MsgId, PSTRUCT_DESC desc)
{PNR_STRUCT_UPDATE head = start;char* buffstart = head->buff;int value;long long llvalue;float fvalue;double dbval;CStringA szTmp, _tmp, szTxt, _tmp1;CString wTmp;CStringA txtOut;int iProc = 0;while (iProc < head->Count){short* sRead = (short*)buffstart;buffstart = buffstart + 2;char* sIndex = buffstart;short icount = sIndex[0];_tmp.Format("%s[%d]", desc[head->StructIndex].name, sRead[0]);txtOut = txtOut + _tmp;//buffstart = buffstart + 1;//buffstart = buffstart - 2;buffstart = buffstart - 1;switch (desc[head->StructIndex].buff[icount]){case 0:AfxMessageBox(L"0号信息!"); break;case 1:value = ToChar(buffstart);szTmp.Format(".value_%d = %d", icount, value);break;case 2:value = ToShort(buffstart);szTmp.Format(".value_%d = %d", icount, value);break;case 3:value = ToInt(buffstart);szTmp.Format(".value_%d = %d", icount, value);break;case 4:llvalue = ToLLong(buffstart);szTmp.Format(".value_%d = %lld", icount, llvalue);break;case 5:fvalue = ToFloat(buffstart);szTmp.Format(".value_%ds = %f", icount, fvalue);break;case 6:dbval = ToDouble(buffstart);szTmp.Format(".value_%d = %lf", icount, dbval);break;case 7:_tmp = ToAscii(buffstart);szTmp.Format(".value_%d = %s", icount, _tmp.GetBuffer());break;case 8:wTmp = ToUniode(buffstart);_tmp = wTmp;szTmp.Format(".value_%d = %s", icount, _tmp.GetBuffer());break;case 9:llvalue = ToLLong(buffstart);szTmp.Format(".value_%d = %llX", icount, llvalue);break;default:break;}txtOut = txtOut + szTmp + "\r\n";        iProc++;};anly->SendData(TTYPE::I_DIS, MsgId, txtOut.GetBuffer(), txtOut.GetAllocLength() + 1);
}
void GameAnly::CreateObjectfiles(POBJ_DESC desc, int icount)
{/*char* _GameOBJECThpp = "F:\\代码存放地\\c\\titan\\tilib\\GameOBJECT.h";char* _GameOBJECTcpp = "F:\\代码存放地\\c\\titan\\tilib\\GameOBJECT.cpp";char* _GameOBJECTdef = "F:\\代码存放地\\c\\titan\\tilib\\GameOBJECTDef.h";*/char* _GameOBJECThpp = "D:\\代码存放地\\c\\titan\\tilib\\GameOBJECT.h";char* _GameOBJECTcpp = "D:\\代码存放地\\c\\titan\\tilib\\GameOBJECT.cpp";char* _GameOBJECTdef = "D:\\代码存放地\\c\\titan\\tilib\\GameOBJECTDef.h";std::ofstream ofs(_GameOBJECThpp); // 根据09数据包生成类的头文件std::ofstream ofCpp(_GameOBJECTcpp); // 根据09数据包生成类的cpp文件std::ofstream ofDef(_GameOBJECTdef);// 生成宏if (ofs.bad() || ofCpp.bad() || ofDef.bad()) {ofs.close();ofCpp.close();ofDef.close();return;}else{// 定义CPP文件头部ofCpp << "#include \"pch.h\"" << std::endl;ofCpp << "#include \"GameOBJECT.h\"" << std::endl;ofCpp << "#include \"GameOBJECTDef.h\"" << std::endl;ofCpp << "void GAMEOBJECT::UpdateData(char*& buffStart)" << std::endl;ofCpp << "{                                                              " << std::endl;ofCpp << "    short* id = (short*)buffStart;" << std::endl;ofCpp << "    Isfree = false;" << std::endl;ofCpp << "    /*                                                         " << std::endl;ofCpp << "        1B 00 buffStart                                        " << std::endl;ofCpp << "        0C 00 00 00 buffStart + 2                              " << std::endl;ofCpp << "        CA 4E 5A 66 53 62 01 80 4E 86 00 00 1D 00              " << std::endl;ofCpp << "    */                                                         " << std::endl;ofCpp << "    buffStart = buffStart + 2;" << std::endl;ofCpp << "    switch (id[0])" << std::endl;ofCpp << "    {" << std::endl;// 定义文件头部区域ofDef << "#pragma once" << std::endl;// 头部生成区域ofs << "#pragma once" << std::endl;ofs << "#define GASCII CStringA" << std::endl;ofs << "#define GUNICODE CString" << std::endl;ofs << "#define GOBJECT long long // LastObject" << std::endl;ofs << "typedef class GAMEOBJECT{" << std::endl;ofs << "public:" << std::endl;ofs << "    bool Isfree = true;" << std::endl;// 变量声明//  i = 1的原因是游戏的数据类型表里(接收的09数据包)第一个是NONEfor (int i = 1; i < icount; i++){char* valueName = desc[i].name;int valueType = desc[i].type;char* valueTypeName = data_desc[2][valueType].name;int valueSize = data_desc[2][valueType].lenth;ofs << "    " << valueTypeName << " " << valueName << ";" << std::endl;ofDef << "#define INDEX_" << valueName << " " << i << std::endl;ofCpp << "    case INDEX_" << valueName << ":" << std::endl;ofCpp << "      return Set" << valueName << "(buffStart);" << std::endl;}ofCpp << "    }" << std::endl;ofCpp << "}" << std::endl;// 函数声明ofs << "    void virtual UpdateData(char*& buffStart);" << std::endl;ofs << "    void virtual Release();" << std::endl;ofs << "protected:" << std::endl;for (int i = 1; i < icount; i++){char* valueName = desc[i].name;int valueType = desc[i].type;char* valueTypeName = data_desc[2][valueType].name;int valueSize = data_desc[2][valueType].lenth;ofs << "    void virtual Set" << valueName << "(char*& buffStart);" << std::endl;ofCpp << "void GAMEOBJECT::Set" << valueName << "(char*& buffStart)" << std::endl;ofCpp << "{" << std::endl;if(valueType == 7){ofCpp << "   int* lenth = (int*)buffStart;" << std::endl;ofCpp << "   buffStart += 4;" << std::endl;ofCpp << "   " << valueName << " = (char*)buffStart; " << std::endl;ofCpp << "   buffStart += lenth[0];" << std::endl;}else if(valueType == 8) {ofCpp << "   int* lenth = (int*)buffStart;" << std::endl;ofCpp << "   buffStart += 4;" << std::endl;ofCpp << "   " << valueName << " = (wchar_t*)buffStart; " << std::endl;ofCpp << "   buffStart += lenth[0];" << std::endl;}else {ofCpp << "    " << valueTypeName << "* value = (" << valueTypeName << "*)buffStart;" << std::endl;ofCpp << "    buffStart += sizeof(" << valueTypeName << ");" << std::endl;ofCpp << "    " << valueName << " = value[0];" << std::endl;}ofCpp << "}" << std::endl;}ofCpp << "void GAMEOBJECT::Release()" << std::endl;ofCpp << "{                                                              " << std::endl;for (int i = 1; i < icount; i++){char* valueName = desc[i].name;int valueType = desc[i].type;char* valueTypeName = data_desc[2][valueType].name;int valueSize = data_desc[2][valueType].lenth;if (valueType == 7) {ofCpp << "    " << valueName << " = \"\";" << std::endl;}else if (valueType == 8) {ofCpp << "    " << valueName << " = L\"\";" << std::endl;}else {ofCpp << "    " << valueName << " = 0;" << std::endl;}}ofCpp << "    Isfree = true;" << std::endl;ofCpp << "}" << std::endl;ofs << "}*PGAMEOBJ;" << std::endl;}ofs.close();ofCpp.close();ofDef.close();
}//void InitStruct(PSTRUCT_DESC desc, int icount, short* offset) {
//    GameAnly* p1 = nullptr;
//    unsigned ioffset = 0;
//    for (int i = 0; i < icount; i++)
//    {
//        desc[i].offset = &offset[ioffset];
//        desc[i].offset[0] = &p1.value_0;
//        desc[i].offset[1] = &p1.value_0;
//        
//        ioffset += desc[i].count;
//    }
//}void GameAnly::CreateStructfile(PSTRUCT_DESC desc, int icount)
{char* _GameStructhpp = "F:\\代码存放地\\c\\titan\\tilib\\GameSTRUCT.h";char* _GameStructcpp = "F:\\代码存放地\\c\\titan\\tilib\\GameSTRUCT.cpp";std::ofstream ofs(_GameStructhpp); // 根据0A数据包生成类的头文件std::ofstream ofsCpp(_GameStructcpp);if (ofs.bad() || ofsCpp.bad()) {return;}else {ofsCpp << "#include \"pch.h\"" << std::endl;ofsCpp << "#include \"GameSTRUCT.h\"" << std::endl;ofsCpp << "#include \"NetClass.h\"" << std::endl;ofsCpp << "void InitStruct(PSTRUCT_DESC desc, int icount, short* offset) {" << std::endl;ofsCpp << "    unsigned ioffset = 0;" << std::endl;ofs << "#pragma once" << std::endl;ofs << "#define GASCII CStringA" << std::endl;ofs << "#define GUNICODE CString" << std::endl;ofs << "#define GOBJECT long long" << std::endl;for (int i = 1; i < icount; i++) {char* structName = desc[i].name;ofs << "// [" << std::hex << i << "][" << structName << "]" << std::endl;ofs << std::dec << std::endl;ofs << "typedef class " << structName << "{" << std::endl;ofs << "public:" << std::endl;for (int l = 0; l < desc[i].count; l++) {char valueType = desc[i].buff[l];char* valueTypeName = data_desc[2][valueType].name;ofs << "    " << valueTypeName << " " << "value_" << l << ";" << std::endl;}ofs << "}*P" << structName << ";" << std::endl;ofsCpp << "    P" << structName << " pointer" << i << " = nullptr;" << std::endl;}ofsCpp << "" << std::endl;for (int i = 1; i < icount; i++){ofsCpp << "    desc[" << i << "].offset = &offset[ioffset]; " << std::endl;for (int x = 0; x < desc[i].count; x++){ofsCpp << "    desc[" << i << "].offset[" << x << "] = (short)&pointer" << i << "->value_" << x << "; " << std::endl;}ofsCpp << "    ioffset += desc[" << i << "].count;" << std::endl;}ofsCpp << "}" << std::endl;}
}char GameAnly::ToChar(char*& start)
{char result = start[2];start = start + 3;return result;
}short GameAnly::ToShort(char*& start)
{short* result = (short*)(start + 2);start = start + 2 + 2;return result[0];
}int GameAnly::ToInt(char*& start)
{int* result = (int*)(start + 2);start = start + 2 + 4;return result[0];
}float GameAnly::ToFloat(char*& start)
{float* result = (float*)(start + 2);start = start + 2 + 4;return result[0];
}double GameAnly::ToDouble(char*& start)
{double* result = (double*)(start + 2);start = start + 2 + 8;return result[0];
}long long GameAnly::ToLLong(char*& start)
{long long* result = (long long*)(start + 2);start = start + 2 + 8;return result[0];
}char* GameAnly::ToAscii(char*& start)
{int* lenth = (int*)(start + 2);char* result = start + 2 + 4; // +4这个操作是跳过 lenth的值start = start + 2 + 4 + lenth[0];return result;
}wchar_t* GameAnly::ToUniode(char*& start)
{int* lenth = (int*)(start + 2);wchar_t* result = (wchar_t*)(start + 2 + 4); // +4这个操作是跳过 lenth的值start = start + 2 + 4 + lenth[0];return result;
}
#endif // Anly

CUI.cpp文件的修改:修改了 OnInitDialog函数

// CUI.cpp: 实现文件
//#include "pch.h"
#include "htdMfcDll.h"
#include "CUI.h"
#include "afxdialogex.h"
#include "extern_all.h"
// CUI 对话框IMPLEMENT_DYNAMIC(CUI, CDialogEx)CUI::CUI(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_MAIN, pParent), txtDetails(_T("")), txtChat(_T("")), txtChatName(_T(""))
{}CUI::~CUI()
{
}void CUI::SetListView(CListCtrl* lst)
{auto lStyle = GetWindowLongPtr(lst->m_hWnd, GWL_STYLE); // 获取窗口样式lStyle |= LVS_REPORT; // 设置为报表模式SetWindowLongPtr(lst->m_hWnd, GWL_STYLE, lStyle);// 给窗口设置样式auto dStyle = lst->GetExtendedStyle(); // 获取扩展样式dStyle |= LVS_EX_FULLROWSELECT; // 设置选择时选择一行dStyle |= LVS_EX_GRIDLINES; // 画网格线lst->SetExtendedStyle(dStyle); // 设置扩展样式
}void CUI::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_TAB1, mTab);DDX_Control(pDX, IDC_LIST1, lstlog);DDX_Text(pDX, IDC_EDIT1, txtDetails);DDX_Text(pDX, IDC_EDIT3, txtChat);DDX_Text(pDX, IDC_EDIT2, txtChatName);DDX_Control(pDX, IDC_COMBO2, cmbChat);
}BOOL CUI::OnInitDialog()
{CDialogEx::OnInitDialog();SetListView(&lstlog);InstallPage(new CUIWnd_0(this), IDD_PAGE_0, L"角色", TRUE);InstallPage(new CUIWnd_1(this), IDD_PAGE_1, L"周围");InstallPage(new CWndSet(), IDD_PAGE_2, L"设置");InstallPage(new CWndItem(), IDD_PAGE_3, L"装备");InstallPage(new CWndSkill(), IDD_PAGE_4, L"技能");InstallPage(new CWndMail(), IDD_DIALOG2, L"邮件");lstlog.InsertColumn(0, L"消息", 0, 70);lstlog.InsertColumn(1, L"内容", 0, 700);lstlog.InsertColumn(2, L"时间", 0, 200);//PageINJ.Init(wAppPath);//PageRAN.SetAppPath(wAppPath);for (CString & txt : ChatPdName){cmbChat.AddString(txt);}cmbChat.SetCurSel(0);return TRUE;
}bool CUI::InstallPage(CDialogEx* wnd, int IDD_WND, CString&& _Name, BOOL IsShow)
{if (CurPage >= (sizeof(WNDS) / sizeof(CDialogEx*))) return false;Pages[CurPage] = wnd;Pages[CurPage]->Create(IDD_WND, this);//Pages[CurPage]->SetParent(this);Pages[CurPage]->ShowWindow(IsShow);CRect rect;mTab.GetClientRect(&rect);rect.top += 32;rect.left += 5;rect.bottom -= 4;rect.right -= 5;Pages[CurPage]->MoveWindow(&rect);mTab.InsertItem(CurPage, _Name);CurPage++;return true;
}BEGIN_MESSAGE_MAP(CUI, CDialogEx)ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, &CUI::OnTcnSelchangeTab1)ON_WM_TIMER()ON_BN_CLICKED(IDC_BUTTON1, &CUI::OnBnClickedButton1)
END_MESSAGE_MAP()// CUI 消息处理程序void CUI::OnTcnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult)
{// TODO: 在此添加控件通知处理程序代码*pResult = 0;int n = mTab.GetCurSel();for (int i = 0; i < CurPage; i++){Pages[i]->ShowWindow(i == n);}
}PTextManger CUI::getTxtManger()
{if (!txtManger)txtManger = new TextManger("F:\\语言包.txt");return txtManger;
}void CUI::loginok(ROLE_DATA* _roles, int count)
{PushLog(LOGTYPE::SYS, L"账号登录成功");NetClient::loginok(_roles, count);wnds.wndRole->lstRole.DeleteAllItems();CString txtInfos;for (int i = 0; i < count; i++){txtInfos = _roles[i].infos.value();txtInfos = txtInfos + L";";CString txtIndex, txtSex, txtMap, txtJob, txtCamp, txtRace, txtLv;CStringA stxtMap, stxtJob, stxtCamp, stxtRace;txtSex = ReadValue(txtInfos, L"1,", L";");txtMap = ReadValue(txtInfos, L"56,", L";");txtJob = L"job_" + ReadValue(txtInfos, L"37,", L";");txtCamp = L"camp_" + ReadValue(txtInfos, L"35,", L";");txtRace = L"race_" + ReadValue(txtInfos, L"36,", L";");txtLv = ReadValue(txtInfos, L"38,", L";");txtIndex.Format(L"%d", _roles[i].index.value());stxtMap = txtMap;stxtJob = txtJob;stxtCamp = txtCamp;stxtRace = txtRace;txtSex = SexName[txtSex == L"1"];wnds.wndRole->lstRole.InsertItem(0, txtIndex);wnds.wndRole->lstRole.SetItemText(0, 1, _roles[i].name);wnds.wndRole->lstRole.SetItemText(0, 2, txtLv);wnds.wndRole->lstRole.SetItemText(0, 3, txtSex);wnds.wndRole->lstRole.SetItemText(0, 4, getTxtManger()->ReadTextById(stxtCamp.GetBuffer()));wnds.wndRole->lstRole.SetItemText(0, 5, getTxtManger()->ReadTextById(stxtMap.GetBuffer()));wnds.wndRole->lstRole.SetItemText(0, 6, getTxtManger()->ReadTextById(stxtRace.GetBuffer()));wnds.wndRole->lstRole.SetItemText(0, 7, getTxtManger()->ReadTextById(stxtJob.GetBuffer()));}
}bool CUI::Tips(int code)
{CString logName;logName.Format(L"服务器提示:%d", code);PushLog(LOGTYPE::TIPS, logName.GetBuffer());// NetClient::Tips(code);return true;
}bool CUI::OnInited()
{SetTimer(0x10001, 50, NULL);return true;
}bool CUI::OnSvrChat(PCHAT_PRV _coder)
{CString txt;CString txtPd;CString txtName = _coder->name;CString txtInfo = _coder->txt;txt.Format(L"%d", _coder->ChartId.value());AfxMessageBox(txt);switch (_coder->ChartId){case 1:// 附近频道txtPd = L"附近";break;case 2:// 区域频道txtPd = L"区域";break;case 3:// 私聊txtPd = L"接收的私聊";// return OnChatPrivate((PCHAT_PRV)_coder);break;case 6:// 公会频道txtPd = L"公会";break;case 9:// 阵营频道txtPd = L"阵营";break;case 21:// 喊话频道txtPd = L"喊话";// return OnChatPublic((PCHAT_PUB)_coder);break;case 103:// 喊话频道txtPd = L"发送的私信";// return OnChatPublic((PCHAT_PUB)_coder);break;}txt.Format(L"[%s][%s][%s]", txtPd, txtInfo, txtName);PushLog(LOGTYPE::CHAT, txt.GetBuffer());return true;
}bool CUI::OnFall(PFALL_DATA_START _coder)
{NetClient::OnFall(_coder);return !wnds.wndSet->setValue[(unsigned)SETNAME::NeverFall];
}bool CUI::OnMoveWalk(PMOVE_DATA_WALK _coder)
{if (wnds.wndSet->setValue[(unsigned)SETNAME::AddSpeed]){float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;MoveSpeed[0] = wnds.wndSet->OldSpeed;}return true;
}bool CUI::OnMoveJump(PMOVE_DATA_JUMP _coder)
{if (wnds.wndSet->setValue[(unsigned)SETNAME::AddSpeed]){float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;MoveSpeed[0] = wnds.wndSet->OldSpeed;}return true;
}bool CUI::OnMoveWJump(PMOVE_DATA_WJUMP _coder)
{if (wnds.wndSet->setValue[(unsigned)SETNAME::AddSpeed]){float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;MoveSpeed[0] = wnds.wndSet->OldSpeed;}return true;
}CString CUI::ReadValue(CString& txt, wchar_t* key, wchar_t* endStr)
{CString result = L"";int iStart = txt.Find(key);if (iStart > -1) {iStart = iStart + wcslen(key);int iend = txt.Find(endStr, iStart);if (iend > -1)result = txt.Mid(iStart, iend - iStart);}return result;
}void CUI::PushLog(LOGTYPE type, wchar_t* txt)
{struct tm newtiem {};time_t t;time(&t);localtime_s(&newtiem, &t); // 获取时间CString logName;logName.Format(L"%.4d-%.2d-%.2d %.2d:%.2d:%.2d", newtiem.tm_year + 1900, newtiem.tm_mon + 1, newtiem.tm_mday, newtiem.tm_hour, newtiem.tm_min, newtiem.tm_sec);lstlog.InsertItem(0, MsgName[(int)type]);lstlog.SetItemText(0, 1, txt);lstlog.SetItemText(0, 2, logName);
}void CUI::OnTimer(UINT_PTR nIDEvent)
{// wnds.wndAIM->UI();CStringA tmp;tmp.Format("%d", Player.CurArea);txtDetails.Format(L"lv.%d.%s 生命值[%d/%d] 经验值[%d/%d] 当前所在场景[%s](%.2f|%.2f|%.2f)", Player.Level, Player.Name,  Player.HP, Player.MaxHP + Player.MaxHPAdd, Player.PlayerExp, Player.PlayerUpgradeExp, getTxtManger()->ReadTextById(tmp.GetBuffer()), Player.x, Player.h, Player.y);SetDlgItemText(IDC_EDIT1, txtDetails.GetBuffer());// UpdateData(FALSE);__super::OnTimer(nIDEvent);
}void CUI::OnBnClickedButton1()
{int nsel = cmbChat.GetCurSel();UpdateData(TRUE);if (nsel > -1) {if (ChatPdId[nsel] != -1) {Talk(txtChat.GetBuffer(), ChatPdId[nsel]);}else {TalkTo(txtChatName.GetBuffer(), txtChat.GetBuffer());}txtChat = L"";}SetDlgItemText(IDC_EDIT3, txtChat.GetBuffer());}

CUI.h文件的修改:修改了 WNDS结构体,新引入 CWndMail.h头文件

#pragma once
#include "afxdialogex.h"
#include "NetClient.h"
#include "TextManger.h"
//增加页面头文件
#include "CUIWnd_0.h"
#include "CUIWnd_1.h"
#include "CWndSet.h"
#include "CWndItem.h"
#include "CWndSkill.h"
#include "CWndMail.h"//游戏辅助UI类
// CUI 对话框enum class LOGTYPE {TIPS = 0,SYS = 1,CHAT = 2,MAX
};typedef struct WNDS {CUIWnd_0* wndRole;CUIWnd_1* wndAIM;CWndSet* wndSet;CWndItem* wndItem;CWndSkill* wndSkill;CWndMail* wndMail;
}*PWNDS;// #define MAX_PAGE_MAIN 3// 这里用了多重继承,这回有一个问题,函数名一样的会发生冲突
// 所以在继承的时候要注意函数名
class CUI : public CDialogEx,public NetClient
{DECLARE_DYNAMIC(CUI)public:CUI(CWnd* pParent = nullptr);   // 标准构造函数virtual ~CUI();// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_MAIN };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持DECLARE_MESSAGE_MAP()union {CDialogEx* Pages[sizeof(WNDS)/sizeof(CDialogEx*)];WNDS wnds;};short      CurPage = 0;
public:CTabCtrl mTab;virtual BOOL OnInitDialog();bool    InstallPage(CDialogEx* wnd, int IDD_WND, CString&& _Name, BOOL IsShow=FALSE);afx_msg void OnTcnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult);
public:void SetListView(CListCtrl* lst);PTextManger getTxtManger();CListCtrl lstlog;
protected:CString MsgName[(unsigned int)LOGTYPE::MAX]{L"错误",L"系统",L"聊天"};CString SexName[2]{L"男",L"女"};CString ChatPdName[6]{L"附近",L"区域",L"公会",L"阵营",L"喊话",L"私信"};int ChatPdId[6]{1, 2, 6, 9, 21, -1};void PushLog(LOGTYPE type, wchar_t* txt);
protected:void virtual loginok(ROLE_DATA* _roles, int count);bool virtual Tips(int code);bool virtual OnInited();bool virtual OnSvrChat(PCHAT_PRV _coder);//  分发坠落函数bool virtual OnFall(PFALL_DATA_START _coder);// 移动中处理函数bool virtual OnMoveWalk(PMOVE_DATA_WALK _coder);// 跳跃处理函数bool virtual OnMoveJump(PMOVE_DATA_JUMP _coder);// 移动时跳跃bool virtual OnMoveWJump(PMOVE_DATA_WJUMP _coder);// 解析角色的信息,性别、种族、阵营等CString ReadValue(CString&txt, wchar_t* key, wchar_t* endStr);
public:CString txtDetails;afx_msg void OnTimer(UINT_PTR nIDEvent);CString txtChat;CString txtChatName;afx_msg void OnBnClickedButton1();CComboBox cmbChat;
};

GameSTRUCTRENAME.h文件的修改:修改了 RecvLetterRec结构体

#pragma once
#define GASCII CStringA
#define GUNICODE CString
#define GOBJECT long long
// [1][OpenTransPointRec]typedef class OpenTransPointRec{
public:int value_0;
}*POpenTransPointRec;
// [2][capital_rec]typedef class capital_rec{
public:GASCII value_0;char value_1;long long value_2;
}*Pcapital_rec;
// [3][SkillType_Lock_State_Rec]typedef class SkillType_Lock_State_Rec{
public:GASCII value_0;
}*PSkillType_Lock_State_Rec;
// [4][SkillType_Rec]typedef class SkillType_Rec{
public:int value_0;
}*PSkillType_Rec;
// [5][NormalSkill_Pos_Rec]typedef class NormalSkill_Pos_Rec{
public:short value_0;short value_1;short value_2;
}*PNormalSkill_Pos_Rec;
// [6][count_limit_rec]typedef class count_limit_rec{
public:short value_0;short value_1;double value_2;
}*Pcount_limit_rec;
// [7][connect_skill_rec]typedef class connect_skill_rec{
public:GASCII value_0;long long value_1;int value_2;
}*Pconnect_skill_rec;
// [8][PropRefreshCompute]typedef class PropRefreshCompute{
public:GASCII value_0;char value_1;double value_2;double value_3;double value_4;double value_5;double value_6;
}*PPropRefreshCompute;
// [9][HeadDetailRecord]typedef class HeadDetailRecord{
public:char value_0;char value_1;
}*PHeadDetailRecord;
// [a][relive_point_rec]typedef class relive_point_rec{
public:char value_0;GASCII value_1;
}*Prelive_point_rec;
// [b][target_hate_rec]typedef class target_hate_rec{
public:GUNICODE value_0;int value_1;
}*Ptarget_hate_rec;
// [c][cooldown_rec]typedef class cooldown_rec{
public:int value_0;long long value_1;long long value_2;int value_3;
}*Pcooldown_rec;
// [d][nocooldown_team_rec]typedef class nocooldown_team_rec{
public:int value_0;
}*Pnocooldown_team_rec;
// [e][nocooldown_skill_rec]typedef class nocooldown_skill_rec{
public:int value_0;int value_1;
}*Pnocooldown_skill_rec;
// [f][fight_relation_rec]typedef class fight_relation_rec{
public:GOBJECT value_0;short value_1;
}*Pfight_relation_rec;
// [10][attack_back_rec]typedef class attack_back_rec{
public:GOBJECT value_0;char value_1;GUNICODE value_2;
}*Pattack_back_rec;
// [11][fly_path_rec]typedef class fly_path_rec{
public:float value_0;float value_1;float value_2;short value_3;
}*Pfly_path_rec;
// [12][battlewar_statistics]typedef class battlewar_statistics{
public:char value_0;GUNICODE value_1;char value_2;char value_3;int value_4;int value_5;int value_6;int value_7;char value_8;long long value_9;
}*Pbattlewar_statistics;
// [13][ForceReputeRecord]typedef class ForceReputeRecord{
public:short value_0;short value_1;short value_2;short value_3;short value_4;char value_5;char value_6;short value_7;short value_8;
}*PForceReputeRecord;
// [14][guild_player_ralation_record]typedef class guild_player_ralation_record{
public:GUNICODE value_0;char value_1;
}*Pguild_player_ralation_record;
// [15][bc_cooldown_rec]typedef class bc_cooldown_rec{
public:int value_0;long long value_1;long long value_2;int value_3;
}*Pbc_cooldown_rec;
// [16][ReduceCountRec]typedef class ReduceCountRec{
public:char value_0;char value_1;char value_2;
}*PReduceCountRec;
// [17][TomplimitRec]typedef class TomplimitRec{
public:long long value_0;long long value_1;long long value_2;long long value_3;
}*PTomplimitRec;
// [18][ChargeBoxRec]typedef class ChargeBoxRec{
public:GASCII value_0;short value_1;char value_2;long long value_3;long long value_4;
}*PChargeBoxRec;
// [19][ChargeHistoryRec]typedef class ChargeHistoryRec{
public:GASCII value_0;short value_1;long long value_2;long long value_3;
}*PChargeHistoryRec;
// [1a][ChargeCollectRec]typedef class ChargeCollectRec{
public:GASCII value_0;short value_1;long long value_2;long long value_3;
}*PChargeCollectRec;
// [1b][friend_rec]typedef class friend_rec{
public:GUNICODE value_0;char value_1;char value_2;char value_3;short value_4;char value_5;short value_6;char value_7;GASCII value_8;GASCII value_9;int value_10;int value_11;double value_12;double value_13;double value_14;double value_15;GASCII value_16;int value_17;int value_18;
}*Pfriend_rec;
// [1c][unfamiliar_rec]typedef class unfamiliar_rec{
public:GUNICODE value_0;char value_1;char value_2;char value_3;int value_4;GASCII value_5;short value_6;int value_7;
}*Punfamiliar_rec;
// [1d][blacklist_rec]typedef class blacklist_rec{
public:GUNICODE value_0;char value_1;char value_2;char value_3;GASCII value_4;int value_5;int value_6;
}*Pblacklist_rec;
// [1e][enemy_rec]typedef class enemy_rec{
public:GUNICODE value_0;char value_1;char value_2;char value_3;int value_4;int value_5;GASCII value_6;int value_7;
}*Penemy_rec;
// [1f][team_rec]typedef class team_rec{
public:GUNICODE value_0;GASCII value_1;GASCII value_2;float value_3;float value_4;float value_5;char value_6;char value_7;GASCII value_8;char value_9;char value_10;char value_11;long long value_12;GASCII value_13;char value_14;char value_15;char value_16;char value_17;GASCII value_18;int value_19;int value_20;
}*Pteam_rec;
// [20][team_recruit_info_rec]typedef class team_recruit_info_rec{
public:GUNICODE value_0;char value_1;char value_2;char value_3;char value_4;
}*Pteam_recruit_info_rec;
// [21][team_recruit_rec]typedef class team_recruit_rec{
public:char value_0;GUNICODE value_1;char value_2;char value_3;char value_4;char value_5;char value_6;char value_7;char value_8;GUNICODE value_9;long long value_10;
}*Pteam_recruit_rec;
// [22][shortcut_rec]typedef class shortcut_rec{
public:short value_0;GASCII value_1;GASCII value_2;char value_3;
}*Pshortcut_rec;
// [23][equip_skill_rec]typedef class equip_skill_rec{
public:short value_0;GASCII value_1;char value_2;short value_3;
}*Pequip_skill_rec;
// [24][equip_skill_rec_all]typedef class equip_skill_rec_all{
public:short value_0;GASCII value_1;char value_2;short value_3;char value_4;
}*Pequip_skill_rec_all;
// [25][clone_info_record]typedef class clone_info_record{
public:short value_0;char value_1;char value_2;char value_3;short value_4;long long value_5;GASCII value_6;char value_7;short value_8;GUNICODE value_9;char value_10;GASCII value_11;long long value_12;
}*Pclone_info_record;
// [26][clone_pass_info_record]typedef class clone_pass_info_record{
public:short value_0;char value_1;short value_2;long long value_3;long long value_4;short value_5;long long value_6;char value_7;GASCII value_8;char value_9;GASCII value_10;GASCII value_11;GASCII value_12;char value_13;GASCII value_14;
}*Pclone_pass_info_record;
// [27][clone_boss_fight_info_rec]typedef class clone_boss_fight_info_rec{
public:short value_0;GASCII value_1;GASCII value_2;
}*Pclone_boss_fight_info_rec;
// [28][clone_player_fight_info_rec]typedef class clone_player_fight_info_rec{
public:short value_0;char value_1;short value_2;GASCII value_3;
}*Pclone_player_fight_info_rec;
// [29][clone_pass_info_max_record]typedef class clone_pass_info_max_record{
public:short value_0;char value_1;short value_2;long long value_3;long long value_4;short value_5;long long value_6;char value_7;GASCII value_8;char value_9;GASCII value_10;GASCII value_11;GASCII value_12;short value_13;long long value_14;
}*Pclone_pass_info_max_record;
// [2a][clone_boss_fight_info_max_rec]typedef class clone_boss_fight_info_max_rec{
public:short value_0;GASCII value_1;GASCII value_2;
}*Pclone_boss_fight_info_max_rec;
// [2b][clone_player_fight_info_max_rec]typedef class clone_player_fight_info_max_rec{
public:short value_0;char value_1;short value_2;GASCII value_3;
}*Pclone_player_fight_info_max_rec;
// [2c][clone_team_first_into_rec]typedef class clone_team_first_into_rec{
public:short value_0;GUNICODE value_1;short value_2;GASCII value_3;GASCII value_4;
}*Pclone_team_first_into_rec;
// [2d][title_rec]typedef class title_rec{
public:int value_0;int value_1;double value_2;char value_3;double value_4;
}*Ptitle_rec;
// [2e][title_unlock_rec]typedef class title_unlock_rec{
public:int value_0;int value_1;double value_2;char value_3;
}*Ptitle_unlock_rec;
// [2f][title_progress_rec]typedef class title_progress_rec{
public:int value_0;char value_1;char value_2;
}*Ptitle_progress_rec;
// [30][formula_rec]typedef class formula_rec{
public:GASCII value_0;
}*Pformula_rec;
// [31][chatpage_rec]typedef class chatpage_rec{
public:char value_0;GUNICODE value_1;char value_2;char value_3;char value_4;short value_5;float value_6;float value_7;int value_8;int value_9;char value_10;char value_11;char value_12;char value_13;char value_14;char value_15;char value_16;char value_17;char value_18;char value_19;char value_20;char value_21;
}*Pchatpage_rec;
// [32][chatroom_playerlist_rec]typedef class chatroom_playerlist_rec{
public:GUNICODE value_0;GASCII value_1;char value_2;
}*Pchatroom_playerlist_rec;
// [33][PlayerESRec]typedef class PlayerESRec{
public:int value_0;short value_1;long long value_2;char value_3;
}*PPlayerESRec;
// [34][PlayerESCriteriaRec]typedef class PlayerESCriteriaRec{
public:int value_0;int value_1;char value_2;char value_3;int value_4;int value_5;
}*PPlayerESCriteriaRec;
// [35][PlayerESRewardRec]typedef class PlayerESRewardRec{
public:int value_0;char value_1;char value_2;float value_3;GASCII value_4;int value_5;int value_6;int value_7;
}*PPlayerESRewardRec;
// [36][arena_request_rec]typedef class arena_request_rec{
public:GUNICODE value_0;
}*Parena_request_rec;
// [37][player_arena_info_rec]typedef class player_arena_info_rec{
public:char value_0;int value_1;int value_2;int value_3;int value_4;short value_5;short value_6;char value_7;char value_8;char value_9;
}*Pplayer_arena_info_rec;
// [38][AchievementCriteriaProgress]typedef class AchievementCriteriaProgress{
public:int value_0;int value_1;char value_2;int value_3;int value_4;int value_5;
}*PAchievementCriteriaProgress;
// [39][AchievementCompleted]typedef class AchievementCompleted{
public:int value_0;char value_1;GASCII value_2;
}*PAchievementCompleted;
// [3a][AchievementTotalProgress]typedef class AchievementTotalProgress{
public:char value_0;int value_1;int value_2;int value_3;
}*PAchievementTotalProgress;
// [3b][AchievementBonus]typedef class AchievementBonus{
public:int value_0;
}*PAchievementBonus;
// [3c][AchievementTrace]typedef class AchievementTrace{
public:int value_0;
}*PAchievementTrace;
// [3d][ActivityRec]typedef class ActivityRec{
public:int value_0;char value_1;
}*PActivityRec;
// [3e][battlewar_queued_rec]typedef class battlewar_queued_rec{
public:int value_0;GASCII value_1;short value_2;long long value_3;char value_4;
}*Pbattlewar_queued_rec;
// [3f][petshow_rec]typedef class petshow_rec{
public:GOBJECT value_0;GASCII value_1;
}*Ppetshow_rec;
// [40][Pet_MagicianStar_Rec]typedef class Pet_MagicianStar_Rec{
public:char value_0;GASCII value_1;GASCII value_2;GASCII value_3;GASCII value_4;GASCII value_5;char value_6;
}*PPet_MagicianStar_Rec;
// [41][pet_mac_rec]typedef class pet_mac_rec{
public:GASCII value_0;GASCII value_1;char value_2;short value_3;short value_4;char value_5;short value_6;char value_7;
}*Ppet_mac_rec;
// [42][pointdisp_rec]typedef class pointdisp_rec{
public:GASCII value_0;char value_1;
}*Ppointdisp_rec;
// [43][pet_active_rec]typedef class pet_active_rec{
public:GASCII value_0;GASCII value_1;GASCII value_2;char value_3;char value_4;char value_5;char value_6;char value_7;char value_8;char value_9;char value_10;char value_11;char value_12;char value_13;char value_14;char value_15;char value_16;GASCII value_17;
}*Ppet_active_rec;
// [44][pet_item_rec]typedef class pet_item_rec{
public:GASCII value_0;GUNICODE value_1;
}*Ppet_item_rec;
// [45][pet_info_rec]typedef class pet_info_rec{
public:GASCII value_0;short value_1;short value_2;short value_3;float value_4;float value_5;float value_6;float value_7;short value_8;short value_9;float value_10;float value_11;float value_12;float value_13;float value_14;float value_15;short value_16;short value_17;short value_18;short value_19;short value_20;short value_21;short value_22;short value_23;short value_24;short value_25;short value_26;float value_27;short value_28;short value_29;short value_30;short value_31;short value_32;short value_33;short value_34;short value_35;short value_36;GASCII value_37;short value_38;float value_39;float value_40;
}*Ppet_info_rec;
// [46][npc_cooldown_rec]typedef class npc_cooldown_rec{
public:int value_0;long long value_1;long long value_2;int value_3;
}*Pnpc_cooldown_rec;
// [47][active_skill_rec]typedef class active_skill_rec{
public:GASCII value_0;
}*Pactive_skill_rec;
// [48][RecvLetterRec]typedef class RecvLetterRec{
public:GUNICODE sender; // 发件人GASCII value_1; // 校验码bool sysmail; // 是否系统邮件(待定)long long value_3;char value_4;bool urgent;// 紧急GUNICODE title;// 邮件主题GUNICODE txt;// 邮件内容GASCII Money; // 金钱GASCII details; // xml,<Post gold="0" trade="0" time="2024-6-12 21:41:30" urgent="1" />GASCII szTime;// 时间,时间格式 yyyy-MM-dd HH:mm:sschar IsRead; // 打开邮件,GASCII value_12; // 校验码GASCII value_13;char value_14;
}*PRecvLetterRec;
// [49][BackstageLetterRec]typedef class BackstageLetterRec{
public:GASCII value_0;GASCII value_1;char value_2;GUNICODE value_3;GUNICODE value_4;GASCII value_5;GASCII value_6;char value_7;
}*PBackstageLetterRec;
// [4a][AreaLvOneExploreRec]typedef class AreaLvOneExploreRec{
public:int value_0;
}*PAreaLvOneExploreRec;
// [4b][MapMarksRec]typedef class MapMarksRec{
public:GUNICODE value_0;char value_1;int value_2;int value_3;
}*PMapMarksRec;
// [4c][consum_capital_limit]typedef class consum_capital_limit{
public:char value_0;long long value_1;short value_2;long long value_3;
}*Pconsum_capital_limit;
// [4d][daygain_capital_limit]typedef class daygain_capital_limit{
public:char value_0;long long value_1;short value_2;
}*Pdaygain_capital_limit;
// [4e][exchange_ticket_rec]typedef class exchange_ticket_rec{
public:double value_0;long long value_1;long long value_2;
}*Pexchange_ticket_rec;
// [4f][exchange_gold_rec]typedef class exchange_gold_rec{
public:double value_0;long long value_1;long long value_2;
}*Pexchange_gold_rec;
// [50][QuestRecord]typedef class QuestRecord{
public:short value_0;char value_1;char value_2;short value_3;
}*PQuestRecord;
// [51][QuestCriteriaRecord]typedef class QuestCriteriaRecord{
public:short value_0;char value_1;short value_2;short value_3;short value_4;char value_5;
}*PQuestCriteriaRecord;
// [52][QuestRewarded]typedef class QuestRewarded{
public:int value_0;
}*PQuestRewarded;
// [53][QuestRepeatRecord]typedef class QuestRepeatRecord{
public:short value_0;short value_1;short value_2;long long value_3;
}*PQuestRepeatRecord;
// [54][QuestTimeLimitRecord]typedef class QuestTimeLimitRecord{
public:short value_0;long long value_1;long long value_2;
}*PQuestTimeLimitRecord;
// [55][QuestSeriesRecord]typedef class QuestSeriesRecord{
public:GASCII value_0;char value_1;short value_2;
}*PQuestSeriesRecord;
// [56][Menu_Verify_Rec]typedef class Menu_Verify_Rec{
public:short value_0;GASCII value_1;short value_2;
}*PMenu_Verify_Rec;
// [57][CloneRepeatQuestRec]typedef class CloneRepeatQuestRec{
public:short value_0;short value_1;short value_2;short value_3;
}*PCloneRepeatQuestRec;
// [58][PVPTaskProgressRecord]typedef class PVPTaskProgressRecord{
public:GASCII value_0;short value_1;
}*PPVPTaskProgressRecord;
// [59][PVPTaskCurrentRecord]typedef class PVPTaskCurrentRecord{
public:GASCII value_0;char value_1;short value_2;long long value_3;char value_4;char value_5;
}*PPVPTaskCurrentRecord;
// [5a][PVPTaskSubRecord]typedef class PVPTaskSubRecord{
public:short value_0;short value_1;short value_2;
}*PPVPTaskSubRecord;
// [5b][PVPTaskScapegoatRecord]typedef class PVPTaskScapegoatRecord{
public:short value_0;GUNICODE value_1;GUNICODE value_2;int value_3;float value_4;float value_5;float value_6;
}*PPVPTaskScapegoatRecord;
// [5c][PVPTaskFriendKillScapegoatRecord]typedef class PVPTaskFriendKillScapegoatRecord{
public:GUNICODE value_0;
}*PPVPTaskFriendKillScapegoatRecord;
// [5d][PVPTaskScapegoatPosRecord]typedef class PVPTaskScapegoatPosRecord{
public:GUNICODE value_0;short value_1;float value_2;float value_3;float value_4;char value_5;long long value_6;int value_7;
}*PPVPTaskScapegoatPosRecord;
// [5e][PVPTaskFriendHelpScapegoatRecord]typedef class PVPTaskFriendHelpScapegoatRecord{
public:GUNICODE value_0;
}*PPVPTaskFriendHelpScapegoatRecord;
// [5f][PVPHorseRaceTimeRecord]typedef class PVPHorseRaceTimeRecord{
public:long long value_0;long long value_1;long long value_2;
}*PPVPHorseRaceTimeRecord;
// [60][PVPTowerWarTimeRecord]typedef class PVPTowerWarTimeRecord{
public:long long value_0;long long value_1;long long value_2;long long value_3;long long value_4;short value_5;short value_6;
}*PPVPTowerWarTimeRecord;
// [61][PvpPlayerActivityState]typedef class PvpPlayerActivityState{
public:GASCII value_0;char value_1;
}*PPvpPlayerActivityState;
// [62][new_use_lead_skill_rec]typedef class new_use_lead_skill_rec{
public:GASCII value_0;GUNICODE value_1;
}*Pnew_use_lead_skill_rec;
// [63][item_box]typedef class item_box{
public:GASCII value_0;int value_1;
}*Pitem_box;
// [64][everydayrecommend_rec]typedef class everydayrecommend_rec{
public:GASCII value_0;char value_1;char value_2;
}*Peverydayrecommend_rec;
// [65][boxstate_rec]typedef class boxstate_rec{
public:GASCII value_0;char value_1;char value_2;
}*Pboxstate_rec;
// [66][player_signin_rec]typedef class player_signin_rec{
public:char value_0;int value_1;int value_2;long long value_3;GASCII value_4;GASCII value_5;char value_6;
}*Pplayer_signin_rec;
// [67][special_npc_rec]typedef class special_npc_rec{
public:GOBJECT value_0;GASCII value_1;float value_2;float value_3;float value_4;char value_5;
}*Pspecial_npc_rec;
// [68][mode_selected_rec]typedef class mode_selected_rec{
public:short value_0;short value_1;long long value_2;long long value_3;short value_4;
}*Pmode_selected_rec;
// [69][charge_config_rec]typedef class charge_config_rec{
public:short value_0;GASCII value_1;GASCII value_2;short value_3;
}*Pcharge_config_rec;
// [6a][charge_capital_rec]typedef class charge_capital_rec{
public:short value_0;long long value_1;long long value_2;long long value_3;
}*Pcharge_capital_rec;
// [6b][PersonalCarrierStore]typedef class PersonalCarrierStore{
public:GASCII value_0;short value_1;char value_2;short value_3;short value_4;GASCII value_5;
}*PPersonalCarrierStore;
// [6c][player_energy_well_record]typedef class player_energy_well_record{
public:int value_0;char value_1;int value_2;char value_3;char value_4;GUNICODE value_5;
}*Pplayer_energy_well_record;
// [6d][player_battle_carrier_record]typedef class player_battle_carrier_record{
public:GASCII value_0;int value_1;int value_2;int value_3;int value_4;int value_5;int value_6;int value_7;GUNICODE value_8;long long value_9;GUNICODE value_10;long long value_11;int value_12;
}*Pplayer_battle_carrier_record;
// [6e][netbar_right_rec]typedef class netbar_right_rec{
public:char value_0;int value_1;int value_2;int value_3;GASCII value_4;
}*Pnetbar_right_rec;
// [6f][rec_energywell_guildwar_member]typedef class rec_energywell_guildwar_member{
public:GUNICODE value_0;char value_1;char value_2;GUNICODE value_3;int value_4;int value_5;int value_6;long long value_7;long long value_8;char value_9;char value_10;int value_11;
}*Prec_energywell_guildwar_member;
// [70][rec_energywell_guildwar_relive]typedef class rec_energywell_guildwar_relive{
public:GASCII value_0;char value_1;
}*Prec_energywell_guildwar_relive;
// [71][rec_energywell_pillar_state]typedef class rec_energywell_pillar_state{
public:GASCII value_0;char value_1;int value_2;int value_3;
}*Prec_energywell_pillar_state;
// [72][rec_energywell_ride_info]typedef class rec_energywell_ride_info{
public:GOBJECT value_0;char value_1;
}*Prec_energywell_ride_info;
// [73][rec_ew_cw_battle_info]typedef class rec_ew_cw_battle_info{
public:int value_0;int value_1;
}*Prec_ew_cw_battle_info;
// [74][rec_ew_cw_person]typedef class rec_ew_cw_person{
public:int value_0;GUNICODE value_1;int value_2;int value_3;int value_4;int value_5;int value_6;int value_7;int value_8;int value_9;int value_10;int value_11;int value_12;
}*Prec_ew_cw_person;
// [75][rec_ew_cw_guild]typedef class rec_ew_cw_guild{
public:int value_0;GUNICODE value_1;int value_2;GUNICODE value_3;int value_4;int value_5;int value_6;int value_7;int value_8;int value_9;int value_10;int value_11;int value_12;
}*Prec_ew_cw_guild;
// [76][rec_ew_cw_camp]typedef class rec_ew_cw_camp{
public:int value_0;int value_1;int value_2;int value_3;int value_4;int value_5;int value_6;int value_7;int value_8;int value_9;
}*Prec_ew_cw_camp;
// [77][rec_ew_cw_boss]typedef class rec_ew_cw_boss{
public:int value_0;GOBJECT value_1;int value_2;int value_3;
}*Prec_ew_cw_boss;
// [78][rec_ew_cw_npc]typedef class rec_ew_cw_npc{
public:int value_0;GOBJECT value_1;
}*Prec_ew_cw_npc;
// [79][rec_ew_cw_pillar]typedef class rec_ew_cw_pillar{
public:int value_0;GOBJECT value_1;
}*Prec_ew_cw_pillar;
// [7a][rec_ew_relive]typedef class rec_ew_relive{
public:int value_0;GOBJECT value_1;
}*Prec_ew_relive;
// [7b][rec_ew_relivepos]typedef class rec_ew_relivepos{
public:int value_0;GASCII value_1;
}*Prec_ew_relivepos;
// [7c][pickup_member_rec]typedef class pickup_member_rec{
public:GUNICODE value_0;short value_1;
}*Ppickup_member_rec;
// [7d][link_rec]typedef class link_rec{
public:GUNICODE value_0;float value_1;float value_2;float value_3;float value_4;GOBJECT value_5;
}*Plink_rec;
// [7e][bc_seat_rec]typedef class bc_seat_rec{
public:char value_0;char value_1;GUNICODE value_2;char value_3;int value_4;int value_5;GASCII value_6;GASCII value_7;GOBJECT value_8;
}*Pbc_seat_rec;
// [7f][NpcToRoleRec]typedef class NpcToRoleRec{
public:GASCII value_0;GASCII value_1;
}*PNpcToRoleRec;
// [80][dice_member_rec]typedef class dice_member_rec{
public:GUNICODE value_0;char value_1;char value_2;
}*Pdice_member_rec;
// [81][RaPropertyRec]typedef class RaPropertyRec{
public:char value_0;float value_1;float value_2;
}*PRaPropertyRec;
// [82][EnchaseRec]typedef class EnchaseRec{
public:char value_0;GASCII value_1;GASCII value_2;
}*PEnchaseRec;
// [83][AddMagicRec]typedef class AddMagicRec{
public:int value_0;
}*PAddMagicRec;

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/30342.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

visual studio error MSB8008:

新项目编译的时候&#xff0c;可能由于编译器的版本不一致导致的问题。 你的电脑上有两个不同版本的VS&#xff0c;或者你的程序拷贝到别人的电脑上去运行&#xff0c;或者你是从别人那里拷贝来的项目&#xff0c;而你们俩用的VS版本不一样&#xff0c;就会在运行的时候出现这…

成都爱尔周进院长提醒毕业生摘镜,术式如何挑

高考完迎来一个悠长假期&#xff0c;考后放松的同时&#xff0c;也有不少同学开始“准备”。 为奔赴梦想&#xff0c;为了理想的专业和学校&#xff0c;不少人决定摘镜。 不少专业有视力要求&#xff0c;且不同专业方向的要求各有不同。我们先来看看有视力要求的专业有哪些&am…

数据集制作——语义分割前png、jpg格式标签图转yolo格式.txt文件(附代码)

&#x1f4aa; 专业从事且热爱图像处理&#xff0c;图像处理专栏更新如下&#x1f447;&#xff1a; &#x1f4dd;《图像去噪》 &#x1f4dd;《超分辨率重建》 &#x1f4dd;《语义分割》 &#x1f4dd;《风格迁移》 &#x1f4dd;《目标检测》 &#x1f4dd;《暗光增强》 &a…

从0开始C++(二):类、对象、封装

目录 类&对象的概念 类的内容 对象的创建 ● 栈内存对象 ● 堆内存对象 封装 类&对象的概念 类和对象是一个比较抽象的概念&#xff0c;这里直接用一个实例方便理解。 类&#xff1a;类是一个抽象的概念&#xff0c;用来描述同一类对象的特点&#xff08;比如&am…

第九届信也科技杯全球AI算法大赛——语音深度鉴伪识别参赛A榜 0.968961分

遗憾没有进复赛&#xff0c;只是第41名。先贴个A榜的成绩。A榜的前三十名晋级&#xff0c;个个都是99分的大佬&#xff0c;但是B榜的成绩就有点低了&#xff0c;应该是数据不同源的问题&#xff0c;第一名0.78分。官网链接&#xff1a;语音深度鉴伪识别 官方baselin:https://g…

Springboot 权限认证框架 -- SA-Token 简介(一)

引言 现今的软件开发中&#xff0c;权限认证与访问控制是每一个应用都必不可少的功能。SA-Token是一个简单、安全、易用的权限认证框架&#xff0c;它主要解决登录认证、权限认证、Session会话、单点登录等功能。SA-Token以其轻量级、零学习成本的特点&#xff0c;迅速赢得了开…

Linux mongodb安装及简单使用

说明&#xff1a;本文章主要是对mongodb的单击安装 1.创建文件夹&#xff0c;准备安装包 cd /user/local mkdir tools 2.解压mongodb包 mkdir mongodb tar -xvf mongodb-linux-x86_64-rhel70-5.0.11.tgz -C mongodb 3.进入解压目录 cd mongodb cd mongodb-linux-x86_64-…

emm, ComfyUI的作者从Stability.AI离职了

&#x1f356;背景 今天在更新ComfyUI的过程中&#xff0c;看到Manager中有这样一段描述&#xff1a; 嗯&#xff1f;做了新的官方网站&#xff1f;然后开始新篇章&#xff1f; 难道说ComfyUI的作者从Stability.AI离职了&#xff1f; 赶紧点开链接看了下&#xff0c;emm&…

24.bytebuf创建

1.byteBuf创建方法 2.自动动态扩容的 package com.xkj.bound;import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import lombok.extern.slf4j.Slf4j;@Slf4j public class TestByteBuf {public static void main(String[] args) {//bytebuf可以不指定…

Java集合框架源码分析:LinkedList

文章目录 一、LinkedList特性二、LinkedList底层数据结构三、LinkedList继承关系参考&#xff1a; 一、LinkedList特性 特性描述是否允许为空允许是否允许重复数据允许是否有序有序是否线程安全非线程安全 二、LinkedList底层数据结构 LinkedList同时实现了List接口和Deque接…

基于PLC的全自动洗衣机控制系统课设

一、设计题目 1.1课题内容 根据设计参数和控制要求&#xff0c;设计一全自动洗衣机&#xff0c;画出其运行框图及梯形图控制程序的编制&#xff0c;并画出硬件接线图。 1.2设计参数 1.3控制要求 &#xff08;1&#xff09;按下启动按扭及水位选择开关&#xff0c;开始进水直…

「51媒体-年中大促」天津有哪些媒体资源-媒体宣传服务公司

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 天津的媒体资源相当丰富&#xff0c;涵盖了报纸、电视、广播、新闻门户网站、央媒驻天津机构、视频媒体以及全国媒体资源等多个方面。以下是详细的媒体资源分类和具体信息&#xff1a; 一…

嵌入式web 服务器boa的编译和移植

编译环境&#xff1a;虚拟机 ubuntu 18.04 目标开发板&#xff1a;飞凌OKA40i-C开发板&#xff0c; Linux3.10 操作系统 开发板本身已经移植了boa服务器&#xff0c;但是在使用过程中发现POST方法传输大文件时对数据量有限制&#xff0c;超过1M字节就无法传输&#xff0c;这是…

Nginx-Rewrite

1、Rewrite的定义 rewrite功能就是使用nginx提供的全局变量或自己设置的变量&#xff0c;结合正则表达式和标志位实现url重写以及重定向。rewrite只能放在 server { }, location { }, if { }中&#xff0c;并且只能对域名后边的除去传递的参数外的字符串起作用。 例如location…

进阶必看,3种灵活操作PyTorch张量的高级方法

大家好&#xff0c;在PyTorch中进行高级张量操作时&#xff0c;开发者经常面临这样的问题&#xff0c;如何根据一个索引张量从另一个张量中选取元素。 例如有一个包含数千个特征的大规模数据集&#xff0c;需要根据特定的索引模式快速提取信息。本文将介绍三种索引选择方法来解…

matlab编写微分方程椭圆型方程(一维形式)

文章目录 理论编程实例原代码 理论 椭圆型方程一维格式即常微分方程&#xff0c;边值问题&#xff0c;方程如下所示&#xff1a; 截断误差&#xff1a; 当 h → ∞ h\rightarrow\infty h→∞时&#xff0c;截断误差趋于零&#xff0c;离散方程组成立&#xff0c; 写成矩阵&…

鸿蒙小案例-短视频

参加泡泡玛特写了个小demo,然后给它稍微完善了一下 基于API11 演示效果 hfvideo演示视频 主要功能集中在4个tab页内 1.首页-视频播放页 2.朋友-关注、朋友、粉丝聚合 3.消息-聊天列表 4.我的-当前用户信息展示 主页页面 1.用户主页 2.聊天页面 3.朋友页面 4.视频播放页 因为不…

闲置资源共享平台

摘 要 随着共享经济的高速发展以及人们对物品的需求方面也越来也丰富&#xff0c;而且各大高校的大学生们的购买力也越来越强&#xff0c;随之而来的问题就是身边的闲置资源也越来越多&#xff0c;但是也有许多的大学生对物品的要求方面不是很高&#xff0c;也愿意买下经济实惠…

【计算机网络体系结构】计算机网络体系结构实验-DNS模拟器实验

一、DNS模拟器实验 拓扑图 1. 服务器ip 2. 服务器填写记录 3. 客户端ip以及连接到DNS服务器 4. ping测试

hadoop Yarn资源调度器

概述 Yarn是一个资源调度平台&#xff0c;负责为运算程序提供服务器资源&#xff0c;相当于一个分布式的操作系统平台&#xff0c;而MapReduce等运算程序相当于操作系统之上的应用程序 Yarn基本架构 YARN 主要由ResourceManager、NodeManager、ApplicationMaster、Container …