119.网络游戏逆向分析与漏洞攻防-邮件系统数据分析-邮件读取与删除功能的封装

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

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

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

上一个内容:118.邮件管理的界面与功能设计

码云版本号:e9ad9663fa9e1bdcfad1205763437677dda5b8b4

代码下载地址,在 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的分享

以 118.邮件管理的界面与功能设计 它的代码为基础进行修改

效果图:

上一个内容把邮件的显示从接收的地方处理基本上是处理完了,接下来就是从发送的地方处理(比如邮件的读取、删除)

首先在打开邮箱窗口的时候,如下图,会发送 350 0,接收两个15数据包,15数据包之前在背包物品分析的哪里知道15数据包是用来初始化一个背包结构的,所以邮箱也算一个背包,背包的编码23或25

删除邮件发送了一个跟MD5码一样的东西

这个码是value_12

然后经过对比value_2表示是否度过邮件

下图是一个未读的邮件

已读

是否系统邮件是value_4,101表示系统邮件,1表示普通邮件,为什么说value_4是表示系统邮件或者为什么value_?是什么什么,这都是通过多个数据包对比得出一个结果进行猜测的,就感觉它像

上一个内容中有一个66,通过逆向分析看到66前面要加 ui_system_mail_source_ 这一段,如下图,打开邮箱再下断点,否则看不到下图的 ui_system_mail_source_66

关闭邮箱窗口之前分析的是350 6、350 7、81 3,然后今天发现81 3发送的时机与350 6、350 7不一样(之前一样可能因为巧了),所以直接把81 3给排除了,关闭邮箱窗口是 350 6、350 7

这里有一个350 7

上图单个350 7是点击下图红框的关闭按钮触发的,所以350 6是关闭邮箱窗口,350 7是关闭打开邮件窗口

付费邮件

它有个350 10,它看着像是上图的邮件付费

CWndMail.cpp文件的修改:修改了 OnBnClickedButton1函数

// 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, sender, title;sender = Client->Player.mailBox[i]->sender;title = Client->Player.mailBox[i]->title;txt.Format(L"%s", Client->Player.mailBox[i]->title);if(Client->Player.mailBox[i]->type == 101){CStringA titleA,senderA;titleA = title;senderA = sender;senderA = "ui_system_mail_source_" + senderA;title = txtManger->ReadTextById(titleA.GetBuffer());sender = txtManger->ReadTextById(senderA.GetBuffer());}lstA.InsertItem(0, sender);lstA.SetItemText(0, 0, sender);lstA.SetItemText(0, 1, title);txt = Client->Player.mailBox[i]->szTime;lstA.SetItemText(0, 2, txt);}
}

NetClient.cpp文件的修改:新加 MailBox函数、OpenMailBox函数、CloseMailBox函数、Mail函数、MailEx函数、GetMail函数

#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::MailBox(int optype)
{NET_SEND_BUFF _buff;MAIL_OPERAION _data;_data.opcode.Set(SC_MAIL);_data.optype.Set(optype);/*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::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::OpenMailBox()
{return MailBox(SC_MAIL_OPENBOX);
}bool NetClient::CloseMailBox()
{bool ret;ret = MailBox(SC_MAIL_CLOSEMAIL);return ret && MailBox(SC_MAIL_CLOSEBOX);
}bool NetClient::Mail(const char* guid, int optype)
{NET_SEND_BUFF _buff;MAIL_OPERAION_RD _data;_data.opcode.Set(SC_MAIL);_data.optype.Set(optype);_data.Guid.Set(guid);/*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::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::MailEx(const char* guid, int optype, int opother)
{NET_SEND_BUFF _buff;MAIL_OPERAION_GET _data;_data.opcode.Set(SC_MAIL);_data.optype.Set(optype);_data.Guid.Set(guid);_data.opother.Set(opother);/*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::GetMail(const char* guid)
{bool ret;ret = MailEx(guid);return ret && Mail(guid, SC_MAIL_GETSC);
}// 移动时跳跃
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);
}

NetClient.h文件的修改:新加 MailBox函数、OpenMailBox函数、CloseMailBox函数、Mail函数、MailEx函数、GetMail函数

#pragma once
#include "NetClass.h"
#include "AIM.h"
#include "ITEM.h"
#include "SKILL.h"
#include "GameSTRUCTRENAME.h"#define CAMP_NAME_QH "xuanrenQH"
#define CAMP_NAME_ZE "xuanrenZQ"#define MAX_AIM 0x200enum class OBJECT_TYPE {Equip = 0x01, // 装备栏,18 01 是装备,用于列表交换MountBag = 0x08, // 坐骑栏,18 08 是坐骑背包,用于列表交换Item = 0x02, // 物品栏,18 02 是角色背包,用于列表交换ItemEx = 0x03, // 扩展栏,18 03 是扩展背包,用于列表交换Skill = 0x28,  // 技能栏,18 28 是技能信息,用于列表交换Shop = 0x3D, // 商店,18 3DPickup = 0x50 // 捨取,18 50 是打怪,怪死了之后掉落的捨取弹框
};typedef struct OBJECT_UNION {union {PITEM* item = nullptr;PSKILL* skill;};/*short EquipMax = 0; // 装备栏数据个数short MountMax = 0; // 坐骑栏数据个数short ItemMax = 0; // 物品栏数据个数short ItemExMax = 0; // 扩展栏数据个数short SkillMax = 0; // 技能栏数据个数*/short Count = 0;short MaxCount = 0; // 装备栏数据个数,坐骑栏数据个数,物品栏数据个数,扩展栏数据个数,技能栏数据个数/*PITEM EquipAry = nullptr; // 装备栏,18 01 是装备,用于存放真正的数据PITEM MountBagAry = nullptr; // 坐骑栏,18 08 是坐骑背包,用于存放真正的数据PITEM ItemBagAry = nullptr; // 物品栏,18 02 是角色背包,用于存放真正的数据PITEM ItemExAry = nullptr; // 扩展栏,18 03 是扩展背包,用于存放真正的数据PSKILL SkillAry = nullptr;  // 技能栏,18 28 是技能信息,用于存放真正的数据*/union {PSKILL skillAry = nullptr;PITEM itemAry;void* Pointer;};
}*POBJECT_UNION;typedef bool (*PNetOperation)(char* buff, unsigned len);class NetClient // 监视客户端每一个操作
{typedef bool (NetClient::* DATAPROC)(char*&, unsigned&);
public:AIM Player; // 玩家角色/* 怪物列表,最好排序,使用lId排序,然后使用二分查找实现快速查询结构用链表或者数组都可以怪物或附近玩家这种东西不可能会很多如果太多电脑处理不过来,所以数组设置为0x100大小差不多够用*/PAIM Aimlst[MAX_AIM]{};// 用来控制飞天bool HideMode;/*18 01 是装备18 02 是角色背包18 03 是扩展背包18 08 是坐骑背包18 31 是攻击技能18 28 是移动类型技能18 3D 商店数据18 50 捨取窗口数据*/OBJECT_UNION Equip; // 装备栏,18 01 是装备,用于列表交换OBJECT_UNION MountBag; // 坐骑栏,18 08 是坐骑背包,用于列表交换OBJECT_UNION Item; // 物品栏,18 02 是角色背包,用于列表交换OBJECT_UNION ItemEx; // 扩展栏,18 03 是扩展背包,用于列表交换OBJECT_UNION Skill;  // 技能栏,18 28 是技能信息,用于列表交换OBJECT_UNION Shop; // 商店,18 3DOBJECT_UNION Pickup; // 捨取,18 50 是打怪,怪死了之后掉落的捨取弹框POBJECT_UNION GetGameOBJECTUnion(short MainIndex);// 获取一个物品或技能
protected:PSTRUCT_DESC StructTable = nullptr;short* StructOffSet = nullptr; // 偏移表short MaxStruct = 0; // 结构体数量char* StructTxt = nullptr;POBJ_DESC ObjectTable = nullptr;// 游戏的数据类型表char* ObjectTxt = nullptr;DATAPROC SendProc[0x100];DATAPROC RecvProc[0x100];bool DefaultProc(char*&, unsigned&);PNetOperation NetSend = nullptr;PNetOperation NetRecv = nullptr;protected: // 消息处理函数-SENDbool OnClientlogin(char*& buff, unsigned& len); // 登录数据包的处理 I_LOGINbool OnClientStartCreateRole(char*& buff, unsigned& len);  // 申请进入创建角色界面 I_CREATEROLE_STARTbool OnClientDelRole(char*& buff, unsigned& len);bool OnClientSendCustom(char*& buff, unsigned& len);bool OnClientCreateRole(char*& buff, unsigned& len);bool OnClientSelectRole(char*& buff, unsigned& len);
protected: // 消息处理函数-RECVbool OnSvrTips(char*& buff, unsigned& len);bool OnSvrloginOk(char*& buff, unsigned& len);bool OnSvrStartCreateRole(char*& buff, unsigned& len);bool OnSverNotice(char*& buff, unsigned& len);bool OnSverObject(char*& buff, unsigned& len);bool OnSverStruct(char*& buff, unsigned& len);bool OnSvrObjectInit(char*& buff, unsigned& len);bool OnSvrObjectInitEx(char*& buff, unsigned& len);bool OnSvrUpdateCord(char*& buff, unsigned& len);bool OnSvrUpdateProperty(char*& buff, unsigned& len);bool OnSvrUpdatePropertyMu(char*& buff, unsigned& len);bool OnSvrRemoveObjectMu(char*& buff, unsigned& len);bool OnSvrUpdateCordEx(char*& buff, unsigned& len);bool OnSvrGameBase(char*& buff, unsigned& len);bool OnSvrGameBaseReset(char*& buff, unsigned& len);bool OnSvrGameBaseExChange(char*& buff, unsigned& len);bool OnSvrGameBaseDestroy(char*& buff, unsigned& len);bool OnSvrGameBaseSet(char*& buff, unsigned& len);bool OnSvrStructInit(char*& buff, unsigned& len); // 结构体数据初始化bool OnSvrStructClear(char*& buff, unsigned& len); // 结构体数据重置bool OnSvrStructDelete(char*& buff, unsigned& len); // 结构体数据删除bool OnSvrStructUpdate(char*& buff, unsigned& len); // 结构体数据更新bool UpdateStruct(PAIM aim, short structIndex, char*& buff, short count); // 结构体数据更新bool UpdateStruct(PAIM aim, short structIndex, short index,char*& buff); // 结构体数据更新bool virtual UpdateStructByte(void* base, PAIM aim, short structIndex, short index,char*& buff);bool virtual UpdateStructShort(void* base, PAIM aim, short structIndex, short index,char*& buff);bool virtual UpdateStructInt(void* base, PAIM aim, short structIndex, short index,char*& buff);bool virtual UpdateStructInt64(void* base, PAIM aim, short structIndex, short index,char*& buff);bool virtual UpdateStructfloat(void* base, PAIM aim, short structIndex, short index,char*& buff);bool virtual UpdateStructDouble(void* base, PAIM aim, short structIndex, short index,char*& buff);bool virtual UpdateStructAscii(void* base, PAIM aim, short structIndex, short index,char*& buff);bool virtual UpdateStructUnicode(void* base, PAIM aim, short structIndex, short index,char*& buff);
public:PROLEDATA roles;unsigned rolecount;bool logined = false;
private:bool DelRole(const wchar_t* rolename, unsigned _len);PAIM GetAimById(long long lId);PAIM CreateAim(long long lId);void RemoveAimById(long long lId);POBJECTBASE GetGameOBJECT(short MainIndex, short Index);// 获取一个物品或技能POBJECTBASE ReSetGameOBJECT(short MainIndex, short max);// 交换物品void ExChangeOBJECT(short MainIndex, short IndexFrom, short IndexTo);// 删除物品void DestoryOBJECT(short MainIndex, short Index);
public:// 通过角色名获取附近角色的信息PAIM GetAimByName(const wchar_t* name);// 获取面向float GetFace(float x, float y, float targetX, float targetY);// 通过附近角色名获取它的信息,然后通过它的信息里的坐标,再通过我们角色坐标计算面向,效果就是面向 GetAimByName(name); 这个角色void FaceTo(const wchar_t* name);
public:void virtual Init(PNetOperation _send, PNetOperation _recv);// 模拟接收的数据包bool SetCoord(long long lId, float x, float h, float y, float face);bool SetProperty(long long lId, int ProType, void* value);/*模拟登陆的方法Id是账号Pass是密码它要基于发送的方法实现,因为我们没有连接socket的操作*/bool login(const char* Id, const char* Pass);bool DelRole(const wchar_t* rolename);bool StartCreateRole();// 用于创建角色bool SelectCamp(const char* _campname);// 选择阵营/*性别 0 男 1 女阵营 1 艾森赫特 2 格兰蒂尔种族 1 布冯特人 3 格洛玛人 4 尤恩图人 6 喀什人职业 1 仲裁者 3秘法师 6 猎魔人 8 元素法师脸型 0 1 2 3*/bool CreateRole(wchar_t* name,double sex, double camp, double face, double occu, const char* photo, const char*infos, const char* txt, double faceShape);// 角色创建// 选择角色并且登录进游戏bool SelectRole(const wchar_t* rolename);// 坠落bool Fall();// 瞬移void Teleport(float x, float h, float y, float face);// 模拟停止bool MoveStop(float x, float h, float y, float face);// 原地跳bool MoveJump(float x, float h, float y, float face, float oldy, float xNext, float yNext);// 移动开始bool MoveWalk(float x, float h, float y, float face, float oldy, float xNext, float yNext);// 应该是移动时跳跃bool MoveWJump(float x, float h, float y, float face, float oldy, float xNext, float yNext);// 使用技能bool UseSkill(const char* _skillName, float x, float h, float y, float face, float xTarget = 0, float hTarget = 0, float yTarget = 0, int rInt1 = 0, int rInt2 = 0, int rInt3 = 0);// 使用物品bool UseItem(short BagIndex,short Index);// 交换物品bool ExChangeItem(short BagIndex,short Index, short tBagindex, short tIndex, bool IsEmpty = true);// 丢弃物品bool DropItem(short BagIndex,short Index, short Amount);// 拆分物品bool SplitItem(short BagIndex, short Index, short tBagindex, short tIndex, short Amount);// 召唤或解除坐骑bool Mount(short Index);// 拾取物品bool PickItem(short id, short Index);// 商店购买物品bool BuyItem(int shopPage, int shopIndex, int itemIndex, int Amount);// 卖物品给商店bool SoldItem(int MainIndex, int Index, int Amount);// 操作邮箱bool MailBox(int optype);// 打开邮箱窗口bool OpenMailBox();// 关闭邮箱窗口bool CloseMailBox();// 删除邮件bool Mail(const char* guid, int optype = SC_MAIL_READ);// 接收附件bool MailEx(const char* guid, int optype = SC_MAIL_GET, int opother = -1);// 接收附件bool GetMail(const char* guid);// 根据角色名字获取一个登录成功数据包(选择角色列表里的一个数据)PROLEDATA GetRoleByName(const wchar_t* rolename);bool Talk(wchar_t* txt, int PdId = 1, double un = 0.0);bool TalkTo(wchar_t* name, wchar_t* txt, double un = 0.0);bool HeartBeep();// 心跳数据包(5秒)bool HeartLoop();// 延迟心跳数据包(20秒)bool Backtoroles(); // 返回到选择角色界面
public:// 用于拦截游戏删除角色功能bool virtual OnDelRole(wchar_t* rolename, unsigned _len);// 用于拦截游戏登录功能void virtual Onlogin(const char* Id, const char*Pass);// 用于拦截游戏创建角色功能bool virtual OnStartCreateRole(int code);// 拦截创建角色bool virtual OnCreateRole(PNS_CREATEROLE _header, PCREATE_ROLE_DATAS _body);// opcode意思是操作码,count意思是数量,buffStart意思是解码的内容开始,buffend意思是解码的内容结束,buffer是原始的数据,len是原始数据的长度// char& buffer, int& len这俩参数带&的原因是,在 OnSendCustom 里进行修改之后,通过&的方式传递回去bool virtual OnSendCustom(PNET_SEND_CHEAD _coder, char*& buffer, unsigned& len);// 拦截0xA开头发送的数据包bool virtual OnSelectRole(wchar_t* rolename);
public:// 针对SendCustom的单独处理bool virtual OnChooseCamp(PNS_CHOOSECAMP _coder);bool virtual OnChat(PCHAT_DATA _coder);bool virtual OnChatPublic(PCHAT_PUB _coder);bool virtual OnChatPrivate(PCHAT_PRV _coder);bool virtual OnHeartBeep(PHEART_BEEP _coder);bool virtual OnHeartLoop(PHEART_LOOP _coder);// 分发移动处理函数bool virtual OnMove(PMOVE_DATA _coder);// 移动中处理函数bool virtual OnMoveWalk(PMOVE_DATA_WALK _coder);// 停止移动处理函数bool virtual OnMoveStop(PMOVE_DATA_STOP _coder);// 跳跃处理函数bool virtual OnMoveJump(PMOVE_DATA_JUMP _coder);// 移动时跳跃bool virtual OnMoveWJump(PMOVE_DATA_WJUMP _coder);//  分发坠落函数bool virtual OnFall(PFALL_DATA_START _coder);// 针对Notice的单独处理bool virtual OnSvrChat(PCHAT_PRV _coder);bool virtual OnUseSkill(PUSESKILL _coder);bool virtual OnInited(); // 发送完了964数据包,表示角色上线public:// 处理失败,参数是错误码bool virtual Tips(int code);void virtual loginok(ROLE_DATA* _roles, int count);bool virtual OnScrStartCreateRole(short code,wchar_t* _txt);bool virtual OnSvrNotice(PNET_SEND_CHEAD _coder, int count, char*& buffer, unsigned& len);
public:bool virtual OnRecvData(char*& buff, unsigned& len);bool virtual OnSendData(char*& buff, unsigned& len);bool virtual OnConnect(char*& ip, unsigned& port);};

NetClass.h文件的修改:新加 SC_MAIL宏、SC_MAIL_OPENBOX宏、SC_MAIL_READ宏、SC_MAIL_GETSC宏、SC_MAIL_DELETE宏、SC_MAIL_CLOSEMAIL宏、SC_MAIL_CLOSEBOX宏、SC_MAIL_GET宏、SC_MAIL_PAY宏、MAIL_OPERAION类、MAIL_OPERAION_RD类、MAIL_OPERAION_GET类

#pragma once
#include "EnCode.h"// 数据包头
// 发送
#define I_LOGIN 0x2 // 登录
#define I_CREATEROLE_START 0x3 // 创建角色发送数据包的头
#define I_SELECT_ROLE 0x04 // 选择角色进入游戏的数据包头
#define I_CREATEROLE 0x05 // 创建角色给服务端发送的数据包头
#define I_DELROLE 0x6 // 删除角色发送数据包的头
#define I_SEND_CUSTOM 0x0A // 进入游戏之后大部分数据包的头// 接收
#define S_TIPS 0x3 // 服务端返回错误的数据包头
#define S_LOGINOK 0x4 // 登录成功的返回数据包的头
// 创建角色服务端反馈的数据(发送03 01 00 00 00这个数据包服务端返回的数据包头)
#define S_CREATEROLE_START 0x05
#define S_OBJECT 0x9 // 数据类型表
#define S_STRUCT 0xA // 里面有玩家角色坐标信息,进入游戏时它有数据结构描述的信息
#define S_UPDATEPRO 0x10 // 更新角色怪物信息
#define S_STRUCT_INITEX 0x11 // 结构体数据创建
#define S_STRUCT_DELETE 0x12 // 删除结构体
#define S_STRUCT_UPDATE 0x13 // 更新结构体
#define S_STRUCT_CLEAR 0x14 // 重置结构
#define S_GAMEBASE_RESET 0x15 // 通知更新数据
#define S_GAMEBASE_SET 0x17 // 初步猜测是 通知更新数据0x15的补充
#define S_GAMEBASE 0x18 // 杂项数据包,里面有技能的信息、装备的信息 还有未知的信息
#define S_GAMEBASE_DROP 0x19 // 删除物品
#define S_NOTICE 0x1E // 里面有聊天数据
#define S_UPDATECORDEX 0x1F // 坐标修正
#define S_UPDATECORD 0x21 // 坐标更新
#define S_NOTICE_COM 0x27 // 里面有聊天数据
#define S_OBJECT_INIT 0x28 // 里面有角色基础信息
#define S_STRUCT_INIT 0x29 // 邮箱初始化或者说是初始化邮件,结构体数据创建
#define S_GAMEBASE_EXCHANGE 0x2B // 物品交换
#define S_UPDATEPROMU 0x2D // 更新信息
#define S_UPDATEPROMU_COM 0x2E // 更新信息
#define S_OBJECT_INITEX_UCOM 0x2F // 里面有附近NPC、玩家初始化信息,与0x30数据包一样只是它未压缩
#define S_OBJECT_INITEX 0x30 // 里面有附近NPC、玩家初始化信息
#define S_OBJECT_REMOVE 0x31 // 附近角色或怪物消失/*最多的数据项, 0A开头的数据包里有数据参数个数,这个宏就是用来设定数据参数个数最大数量是多少,0A开头的数据包目前见过最大数据参数个数是十几个,这里写20应该完全够用,如果不够用到时候再增加
*/
#define MAX_SEND_COUNT 100
#define MAX_RECV_COUNT 100
// 发送数据操作码定义
#define SC_CHOOSECAMP 591 // 阵营选择操作码
#define SC_CHAT 1
#define SC_BEEP 81
#define SC_LOOP 1015
// 游戏客户端处理完进入游戏按钮触发的数据包之后,发送的请求
#define SC_INITED 964
#define SC_REONLINE 860
#define SC_INIT_START 661
#define SC_HAND 962
#define SC_HAND_IN 102#define SC_MOVE_HEADER 15 // 移动
#define SC_FALL_HEADER 890 // 坠入摔血
#define SC_INWATER 478 // 只要发了这个数据包就说明在水下了
#define SC_USESKILL 211 // 使用技能#define SC_ITEM_USE 31 // 使用物品发送的操作码
#define SC_ITEM_EXCHANGE 30 // 交换物品发送的操作码-物品与空位置交换
#define SC_ITEM_EXCHANGEEX 40 // 交换物品发送的操作码-物品与物品交换
#define SC_ITEM_DROP 34 // 丢弃物品发送的操作码
#define SC_ITEM_SPLIT 33 // 拆分物品发送的操作码
#define SC_MOUNT 243 // 召唤或解除坐骑#define SC_ITEM_PICK_START 380 // 拾取物品,后发送
#define SC_ITEM_PICK_END 1008 // 拾取物品,优先发送
#define SC_ITEM_SHOP 70 // 买/卖商店物品的数据头
#define SC_ITEM_SHOP_BUY 20 // 买商店物品操作码
#define SC_ITEM_SHOP_SOLD 21 // 卖物品给商店操作码#define SC_MAIL 350 // 数据包操作码
#define SC_MAIL_OPENBOX 0 // 打开邮箱窗口
#define SC_MAIL_READ 3 // 读取邮件
#define SC_MAIL_GETSC 4 // 收取附件
#define SC_MAIL_DELETE 5 // 删除邮件
#define SC_MAIL_CLOSEMAIL 6 // 关闭邮箱
#define SC_MAIL_CLOSEBOX 7 // 关闭打开邮件窗口
#define SC_MAIL_GET 8 // 收取附件
#define SC_MAIL_PAY 10 // 给邮件付费/*00 00 00 00 00 00 内存对齐补的013 00 数据包头4D 49 00 01 6C 3D 4E 0A 接收者的id48 00 数据类型编号0F 00 数据个数04 00 00 04 00 00 00 72 00 00 00 发邮件的角色名04 00 01 21 00 00 00 35 38 41 39 34 42 43 30 43 44 39 42 34 38 42 34 39 36 33 46 46 37 38 39 46 46 30 42 30 41 35 37 00 校验码04 00 02 0104 00 03 00 8D 27 00 00 00 00 0004 00 04 0104 00 05 0104 00 06 10 00 00 00 71 00 31 00 71 00 31 00 71 00 31 00 31 00 00 00 邮件主题04 00 07 1C 00 00 00 1C 00 71 00 32 00 71 00 32 00 71 00 32 00 71 00 32 00 71 00 32 00 71 00 1D 00 00 00 邮件内容04 00 08 02 00 00 00 30 0004 00 09 42 00 00 00 3C 50 6F 73 74 20 67 6F 6C 64 3D 22 30 22 20 74 72 61 64 65 3D 22 30 22 20 74 69 6D 65 3D 22 32 30 32 34 2D 36 2D 31 32 20 32 30 3A 34 34 3A 35 30 22 20 75 72 67 65 6E 74 3D 22 31 22 20 2F 3E 0A 00 xml的东西里面有时间、是否加急、金币、物品的信息04 00 0A 13 00 00 00 32 30 32 34 2D 36 2D 31 32 20 32 30 3A 34 34 3A 35 30 0004 00 0B 0004 00 0C 21 00 00 00 42 37 30 45 33 41 35 46 41 36 30 41 34 37 42 30 39 38 32 46 43 46 37 35 37 31 44 39 32 34 32 46 00 校验码04 00 0D 02 00 00 00 30 0004 00 0E 01
*/typedef struct NR_STRUCT_UPDATE {char un[6];char op = 0x29;char optype;union {long long lId;unsigned Index[2];};short StructIndex;short Count;char buff[2];
}*PNR_STRUCT_UPDATE;/*29 009A 49 00 01 B1 5C 8C 0A48 00 表示48号结构体00 00 从什么位置开始修改04 00 修改几个11 004D 49 00 01 6C 3D 4E 0A48 0004 00 从什么位置开始01 00 更新几个数据14 00 数据包头C3 45 00 01 4F 32 E7 0A 应该是人物id08 00 结构体序号12 00 数据包头AF 49 00 01 DA 03 50 0A 应该是人物id48 00 结构体序号01 00 删除的邮件序号*/typedef struct NR_STRUCT_INIT {char un[6];char op = 0x29;char optype;union {long long lId;unsigned Index[2];};short StructIndex;union {short Start;short DelIndex;};short Count;char buff[2];
}*PNR_STRUCT_INIT;/*17 op3D 00 背包编码(商店也是属于背包的一种) MainIndex01 00 参数个数 countFB 01 buff[2]0F 00 00 00 53 68 6F 70 5F 79 73 5F 71 68 5F 30 30 31 00 参数
*/
typedef struct NR_GAMEBASE_SET {char un;char op;short MainIndex;unsigned short count;char buff[2];}*PNR_GAMEBASE_SET;/*交换物品的数据包00 为了内存对齐补个02B 02 00 04 00 06 00丢弃接收的数据包00 为了内存对齐补个01902 0004 00
*/
typedef struct NR_GAMEBASE_EXCHANGE {char un;char op = S_GAMEBASE_EXCHANGE;short MainIndex;union {short IndexFrom;short Index;};short IndexTo;
}NR_GAMEBASE_DROP, *PNR_GAMEBASE_DROP, *PNR_GAMEBASE_EXCHANGE;/*00 为了内存对齐补个015 40 00 0E 00 01 00 FA 01 0E 00 00 00 ------------------------------------------00 为了内存对齐补个01828 0013 0005 00BC 01E8 03 00 00 6101 12 00 00 00 53 6B 69 6C 6C 5F 47 6C 31 32 34 30 5F 30 31 5F 31 00F8 01 01 0007 00 01 00 00 00B6 00 20 4E 00 00
*/
typedef struct NR_GAMEBASE {// 15与18数据包的头部,当前用于技能与装备的结构char un;char op;short type;union {short index;short max;};short count;
}NR_GAMEBASE_RESET, *PNR_GAMEBASE, *PNR_GAMEBASE_RESET;
/*1F87 44 00 01 7F B0 D6 05FE AD DE C36C F5 46 4207 FD 36 C490 D9 9C 40
*/
typedef struct NR_UPDATECOORD {char un[6];char len = sizeof(NR_UPDATECOORD) - 7;char op = S_UPDATECORDEX;long long lId;float x;float h;float y;float face;
}*PNR_UPDATECOORD;/*31 01 00 个数9B 49 00 01 D5 8C 98 05 id内存对齐00 00 00 00 00 31 01 00 // 补五个0与id的8字节对齐9B 49 00 01 D5 8C 98 05 
*/
typedef struct NR_OBJECT_REMOVEMU {char un[4];char len;char op = 0x31;short objCount = 0;long long lId[2];// 这里是一个指针,[]里写什么都行
}*PNR_OBJECT_REMOVEMU;
/*角色怪物数据更新结构 2D和2E00 00 00 00 00 2D 01 009B 49 00 01 D5 8C 98 0502 0025 00 18 00 00 0029 00 BA 01 00 00
*/
typedef struct NR_OBJECT_UPDATEPROMU {char un1[4]; // 为了向id数据的8字节对齐char len;char op = 0x2D;short objCount = 0;long long lId;short icount;short itype;
}NR_OBJECT_UPMU, * PNR_OBJECT_UPMU;/*角色怪物基本信息更新 接收的10数据包结构体*/
/*00 00 为了内存对齐补零10 0078 48 00 01 FC 61 79 0501 0029 00 65 09 00 00
*/
typedef struct NR_OBJECT_UPDATEPRO {char un1[5]; // 为了向id数据的8字节对齐char len;char op = 0x10;char MsgId = 0x00;union{long long lId;unsigned Index[2];};short icount = 1;short itype;union{char buff[0x04];int lenth;};char buffEnd[0x196];
}NR_OBJECT_UP, *PNR_OBJECT_UP;
/*角色怪物初始化结构00 00 00 00 00 30 0B 0082 0B 00 01 82 0B 00 0069 59 F8 C367 49 FF 41FE 55 9C 42C6 70 BA 40A8 8F 07 C406 52 58 413B D0 2A 43C6 70 BA 4000 00 20 4100 00 00 0000 00 00 0000 00 00 0004 00 00 0011 00
*/typedef struct NR_OBNJECT_INITEX {char un1[4];char len = sizeof(NR_OBNJECT_INITEX) - 7;char op = 0x30;short obj_count;long long lId;float x;float h;float y;float face;float tx;float th;float ty;float tface;int State;float un2[4]{};short icount;short type;
}*PNR_OBJINITEX;// 角色初始化数据
/*28  opE6 44 00 01 39 0A 63 04 lId6F 3A 07 C4 x49 C8 81 41 h46 1E 40 44 yBC 74 03 40 face6F 3A 07 C4 tx49 C8 81 41 th46 1E 40 44 tyBC 74 03 40 tface00 00 00 00 un[0]00 00 00 00 un[1]00 00 00 00 un[2]00 00 00 00 un[3]00 00 00 00 un[4]5E 00 icount多出来的type是为了内存对齐才写的
*/
typedef struct NR_OBNJECT_INIT {char un1[6];char len = sizeof(NR_OBNJECT_INIT) - 9;char op = 0x28;long long lId;float x;float h;float y;float face;float tx;float th;float ty;float tface;float un2[5]{};short icount;short type;
}*PNR_OBJINIT;
// 保存结构数据描述信息的结构体
typedef struct STRUCT_DESC {char* name;int count;// 为了内存对齐这里使用int类型char* buff;short* offset;
}*PSTRUCT_DESC;
// 保存对象数据描述信息的结构体(游戏数据类型表)
typedef struct OBJECT_DESC {char* name;int type;
}*POBJ_DESC;// 数据头结构体 数据结构约定
// 也就是接收到1E包的头部
typedef struct NR_NOTICE_HEAD {char un;char op;short count;
}NR_HEAD, *PNR_HEAD, *PNR_NOTICE_HEAD;// 选择角色头部
typedef struct NET_SEND_SELECTROLE {char op = 0x04;char buff[83]{};
}NS_SELECTROLE, * PNS_SELECTROLE;// 创建角色数据头部
typedef struct NET_SEHD_CREATEROLE_HEAD {/*char un[0x2];char len = sizeof(NET_SEHD_CREATEROLE_HEAD) - 0x03;这俩代码是为了解决内存对齐的问题,创建角色给服务端发送的05开头的数据包,把05变成00 00 00 05*/char un[0x2];char len = sizeof(NET_SEHD_CREATEROLE_HEAD) - 0x03;char op = 0x05;int index = 0x0; // 选择角色列表索引/*宽字节是2字节0x10是16两个是32,正好满足给服务端发送的创建角色数据包,也就是05开头的数据包*/wchar_t name[0x20];short unst = 0x00;short count = 0x08;
}*PNS_CREATEROLE;// 基类
typedef class NET_SEND_BASE {
public:// 实现编码操作,模拟游戏数据包给服务端发送数据,这个模拟的数据包通过调用 CodeMe函数得到unsigned CodeMe(int size, char* buffer);
}NSR_BASE, *PNET_SEND_BASE, * PNSR_BASE;typedef struct NS_CREATEROLE_HEAD_BUFF :public NET_SEHD_CREATEROLE_HEAD {char buff[0x300]{};
}*PNS_CREATEROLEBUFF;// 解析约定结构体
// 创建角色数据结构体
typedef class CREATE_ROLE_DATAS:public NET_SEND_BASE {
public:GDOUBLE sex;//1.000000 性别 0 男 1 女GDOUBLE camp;//1.000000 阵营 1 艾森赫特 2 格兰蒂尔GDOUBLE face;//1.000000 种族 1 布冯特人 3 格洛玛人 4 尤恩图人 6 喀什人GDOUBLE occu;//3.000000 职业 1 仲裁者 3秘法师 6 猎魔人 8 元素法师GCHAR Photo;//gui\BG_team\TeamRole\Teamrole_zq_humF_001.PNGGCHAR Infos;//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;GCHAR Txt;// 细节编辑捏脸GDOUBLE faceSahpe;//0.000000 脸型 0 1 2 3
}* PCREATE_ROLE_DATAS;// 发送数据标准头 0xA数据包
typedef struct NET_SEND_HEAD {// 为了内存对齐,当前结构不可能超过255,所以这样写是没问题的char len = sizeof(NET_SEND_HEAD) - 1;char op = 0x0A;short unst = 0;int unnt[4]{};short unst1 = 0;short count = 0;
}*PNET_SEND_HEAD;
// 开始创建角色的数据结构
// 申请创建角色结构体
typedef struct NET_CREATEROLE_START {char un[0x02];// 用来做内存对齐char len = sizeof(NET_CREATEROLE_START) - 3;// 用来做内存对齐char op = 0x03;int code = 0x01;
}*PNET_CREATEROLE_START;// 删除角色数据结构
typedef struct DATA_DELROLE {char op;char buff[0x1F];int len;int un[8] = { 0x01 , 0x03 };}*PDATADELROLE;/*数据包还原结构体要注意内存对齐,如果数据不满4字节,它字段会补齐比如结构体里有一个char变量,它是1字节,在内存里它可能会为了内存对齐让它变成4字节,所以这要注意
*/
// 登录数据
typedef struct DATA_LOGIN {int op = 0x0300;char buff[0x10]{};int lenId = 0x10;/*这个是登录的账号,它可能会变成0x20或更长,现在默认让它0x10读的时候以长度为准就好了*/char Id[0x10]{};int lenPass = 0x10;/*这个是登录的密码,它可能会变成0x20或更长,现在默认让它0x10读的时候以长度为准就好了*/char Pass[0x10]{};int lenCode = 0x10;char Code[0x10]{};int eop = 0x01;
}*PDATALOGIN;
typedef struct DATA_LOGIN_OK {// 登录成功数据包头int un[8] = { 0, 0, 0x76B, 0x0C, 0x1E,0, 0, 0 };int index = 0;int RoleCount = 0;
}*PDATALOGINOK;// 发送数据包含内存空间,也就是数据参数,数据参数的意思看44文章里的内容
typedef struct NET_SEND_BUFF:public NET_SEND_HEAD {char buff[0x1000]{};
}*PNET_SEND_BUFF;typedef class  NET_SEND_CHEAD:public NET_SEND_BASE {
public:union {GCHAR msgHeader;GINT opcode;};
public:NET_SEND_CHEAD() {};~NET_SEND_CHEAD() {};
}NSR_CHEAD, *PNSR_CHEAD, *PNET_SEND_CHEAD;// 选择角色
typedef class NET_SEND_CHOOSECAMP :public NET_SEND_CHEAD {
public:GCHAR camps;
}*PNS_CHOOSECAMP;// 心跳包数据结构
typedef class HEART_BEEP :public NET_SEND_CHEAD {
public:// 20秒一次GINT tick;//3
}*PHEART_BEEP;typedef class HEART_LOOP :public NET_SEND_CHEAD {
public:// 5秒一次GINT64 tick;//9320695GCHAR txt;//}*PHEART_LOOP;typedef struct ONLINE_HAND: public NSR_CHEAD{GINT step; // 2GINT state; // 1
}*PONLINE_HAND;typedef struct ONLINE_INIT : public NSR_CHEAD {GINT state;//0GDOUBLE un;//180000000.000000
}*PONLINE_INIT;
// 登陆后角色数据区
// 聊天数据包的数据结构
typedef class CHAT_DATA :public NET_SEND_CHEAD {
public:GINT ChartId;//1
}*PCHAT_DATA;
typedef class CHAT_PUBLIC :public CHAT_DATA {
public:GUTF16 txt;//[222222222222222222222222222222222222222222<img src="Face37"  valign="bottom"  only="line"/>]GDOUBLE un;//0.000000
}*PCHAT_PUB;
typedef class CHAT_PRIVATE :public CHAT_DATA {
public:GUTF16 txt;//[222222222222222222222222222222222222222222<img src="Face37"  valign="bottom"  only="line"/>]GUTF16 name;//[皮革兔]GDOUBLE un;//0.000000
}*PCHAT_PRV;// 登陆后角色数据包
typedef class ROLE_DATA {// 登录成功数据包
public:GBYTE byte;GINT index;GINT un1;GUTF16 name;GUTF16 infos;GINT un2;GINT64 un3;
}*PROLEDATA;typedef class MOVE_DATA :public NET_SEND_CHEAD {
public:GINT Mode; // 0停止 1移动中 2跳跃GINT Count; // 带入场景这里就是一共有几个与坐标相关的数据
}*PMOVE_DATA;// 停止移动
typedef class MOVE_DATA_STOP :public MOVE_DATA {
public:GFLOAT x;//-584.845459GFLOAT h;//65.004677GFLOAT y;//708.458740 GFLOAT face;//4.912942
}*PMOVE_DATA_STOP;// 移动
typedef class MOVE_DATA_WALK :public MOVE_DATA {
public:GFLOAT x;//-584.845459 当前坐标 xGFLOAT h;//65.004677 当前坐标 hGFLOAT y;//708.458740 当前坐标 yGFLOAT xNext;//-596.604919 预计移动到的坐标GFLOAT yNext;//710.849304 预计移动到的坐标GFLOAT MoveSpeed;//5.000000 移动速度GFLOAT GSpeed;//0.000000 根据跳跃的数据包猜测它是重力加速(也就是坠落的速度)GFLOAT face;//4.912942 面向
}*PMOVE_DATA_WALK;// 跳跃或往前跳(前后左右跳)
typedef class MOVE_DATA_JUMP:public MOVE_DATA {
public:GFLOAT x;//-599.624939GFLOAT h;//65.004105GFLOAT y;//711.464600GFLOAT xNext;//-599.624939GFLOAT yNext;//711.464600GFLOAT MoveSpeed;//5.000000GFLOAT JumpSpeed;//4.500000GFLOAT GSpeed;//9.800000 重力加速(也就是坠落的速度)GFLOAT face;//4.912942
}*PMOVE_DATA_JUMP;// 移动时跳跃
typedef class MOVE_DATA_WJUMP :public MOVE_DATA {
public:GFLOAT x;//-394.622162GFLOAT h;//8.719633GFLOAT y;//912.655151GFLOAT xNext;//-400.995270GFLOAT yNext;//902.487366GFLOAT MoveSpeed;//50.000000GFLOAT face;//3.701483
}*PMOVE_DATA_WJUMP;// 开始坠落
typedef class FALL_DATA_START :public NET_SEND_CHEAD {
public:GINT Mode;//890GINT StartH;//1GFLOAT NextH;//58.223557GINT EndH;//0}*PFALL_DATA_START;// 坠落结束
typedef class FALL_DATA_STOP :public NET_SEND_CHEAD {
public:GINT Mode;//2GFLOAT StartH;//58.223557GFLOAT NextH;//48.128914GFLOAT EndH;//24.581387
}*PFALL_DATA_STOP;// 释放技能结构
typedef class USESKILL_DATA :public NET_SEND_CHEAD {
public://GINT gint;//211GCHAR skillName;//Skill_In1025_01_1GFLOAT x;//-522.842712,猜测它是使用技能的坐标GFLOAT h;//8.122560,猜测它是使用技能的坐标GFLOAT y;//866.518250,猜测它是使用技能的坐标GFLOAT face;//5.872537 面向GFLOAT xTarget;//0.000000 释放技能的目标位置,也就是技能释放到哪GFLOAT hTarget;//0.000000 释放技能的目标位置,也就是技能释放到哪GFLOAT yTarget;//0.000000 释放技能的目标位置,也就是技能释放到哪GINT un0;//0GINT un1;//0GINT un2;//1
}*PUSESKILL;/*装备替换GINT gint;//40GINT gint;//2GINT gint;//1GINT gint;//1GINT gint;//3装备装备(注意这个不是替换装备,这是比如帽子这个装备,然后当前身上并没有装备帽子,帽子在背包中,这时装备帽子就会是下方的数据包)GINT gint;//30GINT gint;//2GINT gint;//20GINT gint;//1GINT gint;//1物品数量拆分GINT gint;//33GINT gint;//2GINT gint;//3GINT gint;//2GINT gint;//18GINT gint;//3物品合并GINT gint;//40GINT gint;//2GINT gint;//18GINT gint;//2GINT gint;//3物品交换:物品与物品交换GINT gint;//40GINT gint;//2GINT gint;//6GINT gint;//2GINT gint;//5物品交换:物品与空位置交换GINT gint;//30GINT gint;//2GINT gint;//5GINT gint;//2GINT gint;//4使用物品GINT gint;//31 使用物品的操作码GINT gint;//2 背包编号GINT gint;//15 物品在背包中的位置丢弃物品GINT gint;//34 丢弃物品的操作码GINT gint;//2 背包编号GINT gint;//1 物品在背包中的位置GINT gint;//3 数量
*/
// 召唤或解除坐骑
typedef class MOUNT_DATA :public NET_SEND_CHEAD {
public:GINT Index;
}ITEM_PICK_DATA,*PMOUNT_DATA, *PMOUNT_DATA;
// 使用物品发送的数据包的结构
typedef class ITEMOP_DATA :public NET_SEND_CHEAD {// 物品丢弃、使用、拆分、合并交换相关数据包的结构
public:GINT MainIndex; // 背包编码GINT Index; // 物品所在背包的位置
}ITEM_USE_DATA, *PITEMOP_DATA, *PITEM_USE_DATA;
// 丢掉物品发送的数据包的结构
typedef class ITEM_DROP_DATA :public ITEMOP_DATA {
public:GINT Amount; // 物品的数量
}*PITEM_DROP_DATA;
// 交换物品
typedef class ITEM_EXCHANGE_DATA :public ITEMOP_DATA {
public:GINT TargetId; // 背包编号,在这里的意思是交换到什么背包里GINT TargetIndex; // 物品所在背包的位置,也就是物品在 TargetId 里什么位置
}*PITEM_EXCHANGE_DATA;
// 拆分物品
typedef class ITEM_SPLIT_DATA :public ITEMOP_DATA {
public:GINT TargetId; // 背包编号,在这里的意思是拆分到什么背包里GINT TargetIndex; // 物品所在背包的位置,也就是物品在 TargetId 里什么位置GINT TargetAmount; // 拆分的数量
}*PITEM_SPLIT_DATA;/*GINT gint;//70 数据头GINT gint;//20 操作码GCHAR gchar;//Shop_ys_qh_001 商店idGINT gint;//1 商店物品页码GINT gint;//1GINT gint;//4 物品所在商店位置GINT gint;//1 数量GINT gint;//0GINT gint;//0
*/
typedef class ITEM_BUY_DATA : public NET_SEND_CHEAD {
public:GINT opMode;//20 操作码GCHAR ShopId;//Shop_ys_qh_001 商店idGINT ShopPage;//1 商店物品页码GINT ShopIndex;//1GINT Index;//4 物品所在商店位置GINT Amount;//1 数量GINT un1;//0GINT un2;//0
}*PITEM_BUY_DATA;/*GINT gint;//70GINT gint;//21GINT gint;//0GCHAR gchar;//Shop_ZH_005GINT gint;//2GINT gint;//1GINT gint;//30
*/
typedef class ITEM_SOLD_DATA : public NET_SEND_CHEAD {
public:GINT opMode;//21GINT un1;//0GCHAR ShopId;//Shop_ZH_005GINT MainIndex;//2GINT Index;//1GINT Amount;//30
}*PITEM_SOLD_DATA;/*打开邮箱窗口GINT gint;//350GINT gint;//3GCHAR gchar;//2C3B97C1C6E542AD90E540E6A4C8754C删除邮件GINT gint;//350GINT gint;//5GCHAR gchar;//B70E3A5FA60A47B0982FCF7571D9242F
*/
typedef class MAIL_OPERAION : public NET_SEND_CHEAD {
public:GINT optype;//3// GCHAR gchar;//2C3B97C1C6E542AD90E540E6A4C8754C
}*PMAIL_OPERAION;// 邮件的读取删除
typedef class MAIL_OPERAION_RD : public MAIL_OPERAION {
public:GCHAR Guid;//2C3B97C1C6E542AD90E540E6A4C8754C
}*PMAIL_OPERAION_RD;/*附件收取GINT gint;//350GINT gint;//8GCHAR gchar;//6AB6F03436154524A73CFF5C12D6691CGINT gint;//-1
*/
typedef class MAIL_OPERAION_GET : public MAIL_OPERAION_RD {
public:GINT opother;//-1
}*PMAIL_OPERAION_GET;

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 opened; // 是否打开long long value_3;char type; // 1普通邮件 2付费邮件 101系统邮件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 Guid; // 校验码GASCII TradeMoney; // 交易金额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/news/856401.shtml

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

相关文章

DNS部署与安全

一、DNS 英文全称&#xff1a;Domain Name Service 含义&#xff1a;域名服务 作用&#xff1a;为客户机提供域名解析服务 二、域名组成 域名组成概述 &#xff08;1&#xff09;如"www.sina.com.cn”是一个域名&#xff0c;从严格意义上讲&#xff0c;“sina.com.cn”…

苹果入局AI手机 iOS 18将应用AI功能

当三星、华为等国内外手机厂商都在卷着造AI手机时&#xff0c;智能手机大佬苹果那边确一直没什么动静。直到今年5月&#xff0c;距离苹果 WWDC24 全球开发者大会还有十多天时&#xff0c;长期关注苹果的博社记者Mark Gurman放料&#xff0c;iOS 18系统中将会应用一些AI功能。 从…

玩转Matlab-Simscape(初级)- 10 - 基于COMSOLSimulink 凸轮机构的控制仿真

** 玩转Matlab-Simscape&#xff08;初级&#xff09;- 10 - 基于COMSOL&Simulink 凸轮机构的控制仿真 ** 目录 玩转Matlab-Simscape&#xff08;初级&#xff09;- 10 - 基于COMSOL&Simulink 凸轮机构的控制仿真 前言一、简介二、在Solidworks中创建3D模型&#xff…

PPT可以转换成Word吗?归纳了三种转换方式

PPT可以转换成Word吗&#xff1f;在当今快节奏的工作和学习环境中&#xff0c;不同格式文件之间的转换变得日益重要。PPT作为演示文稿制作的首选工具&#xff0c;广泛应用于会议演讲、教育培训等多个场景&#xff0c;而Word则是文档编辑与编排的基石。为了便于进一步编辑、分享…

远程桌面无法连接,远程桌面连接登录没有成功

在信息技术领域&#xff0c;远程桌面连接作为一种便捷的管理和操作工具&#xff0c;对于企业和个人用户而言都具有极其重要的价值。然而&#xff0c;在实际使用过程中&#xff0c;远程桌面无法连接的问题时常出现&#xff0c;这不仅影响了工作效率&#xff0c;还可能对数据安全…

房间灰尘多怎么办?资深保洁推荐除尘最有效的空气净化器

家中的灰尘问题一直是许多人的烦恼&#xff0c;尤其是对尘螨过敏的人来说&#xff0c;灰尘简直是“心头之患”。常言道&#xff1a;“家有尘埃&#xff0c;心头有累。”每天打扫灰尘成了许多人的烦恼&#xff0c;尤其是对尘螨过敏的人来说&#xff0c;灰尘简直是“心头之患”。…

酷得智能 电子方案开发 单片机方案定制

手持小风扇电子方案开发&#xff0c;东莞酷得智能科技有限公司为您服务 东莞市酷得智能科技有限公司 在消费类电子市场深耕多年&#xff0c;依托于市场团队对市场的敏锐度、工程团队的技术积累、结合自身的创新以及和上游原厂深度合作&#xff0c;在2.4G通信、BLE、语音、马达…

基于TCAD与紧凑模型结合方法探究陷阱对AlGaN/GaN HEMTs功率附加效率及线性度的影响

来源&#xff1a;Investigation of Traps Impact on PAE and Linearity of AlGaN/GaN HEMTs Relying on a Combined TCAD–Compact Model Approach&#xff08;TED 24年&#xff09; 摘要 本文提出了一种新型建模方法&#xff0c;用于分析GaN HEMTs的微波功率性能。通过结合工…

Vue 表格动态添加行/删除行

<template><div class"elife-container"><el-row :gutter"10" class"mb8"><el-col :span"1.5"><el-button type"primary" plain size"mini" click"handleAdd">新增</…

企业微信集成策略:打破壁垒,驱动企业数字化转型

随着全球化和数字化的快速推进&#xff0c;企业如何在激烈的市场竞争中脱颖而出&#xff0c;成为每个企业家和决策者关注的焦点。腾讯推出的企业微信&#xff0c;作为一款集沟通、协作、管理于一体的企业通讯与办公工具&#xff0c;正逐步成为企业数字化转型的得力助手。NetFar…

武汉工程大学24计算机考研数据,有学硕招收调剂,而专硕不招收调剂!

武汉工程大学是一所以工为主&#xff0c;覆盖工、理、管、经、文、法、艺术、医学、教育学等九大学科门类的多科性教学研究型大学&#xff0c;是湖北省重点建设高校、湖北省国内一流学科建设高校&#xff0c;入选卓越工程师教育培养计划、中西部高校基础能力建设工程、“新工科…

spring boot接入nacos 配置中心

再接入nacos配置中心时&#xff0c;需要确认几点&#xff1a; 1. spring boot 版本 (spring boot 2.x ) 2. nacos 配置中心 服务端 版本 (1.1.4) 3. nacos client 客户端版本 (1.1.4) 方式一 1. 启动 nacos 服务端&#xff0c;这里不做解释 在配置中心中加入几个配置 2. 在…

吴恩达机器学习 第三课 week1 无监督机器学习(下)

目录 01 学习目标 02 异常检测算法 2.1 异常检测算法的概念 2.2 基于高斯模型的异常检测 03 利用异常检测算法检测网络服务器的故障 3.1 问题描述 3.2 算法实现 3.3 问题升级 04 总结 01 学习目标 &#xff08;1&#xff09;理解异常检测算法&#xff08;Anomaly Dete…

详解工业网关在线探测功能及用途

详解工业网关在线探测功能及用途 工业网关作为工业物联网&#xff08;IIoT&#xff09;架构中的关键组件&#xff0c;扮演着桥梁的角色&#xff0c;它连接了现场的各类传感器、执行器以及更高级别的云平台或企业系统。在线探测功能是工业网关诸多能力中的一项重要特性&#xf…

2024年文化、艺术设计与社会科学国际学术会议(ICCADSS 2024)

2024年文化、艺术设计与社会科学国际学术会议&#xff08;ICCADSS 2024&#xff09; 重要信息 会议官网&#xff1a;http://www.iccadss.com 会议地址&#xff1a;北京 收录检索&#xff1a;EI,CPCI,CNKI,Google Scholar 投稿邮箱&#xff1a;society_info163.com 投稿标题&am…

clean code-代码整洁之道 阅读笔记(第十一章)

第十一章 系统 “复杂要人命,它消磨开发者的生命&#xff0c;让产品难以规划、构建和测试。” --RayOzzie&#xff0c;微软公司首席技术官 11.1 如何建造一个城市 每个城市都有一组组人管理不同的部分&#xff0c;有些人负责全局&#xff0c;其他人负责细节。 城市能运转&#…

如何解决 torch.cuda.is_available()是False

目录 1. 问题2. 解决方法2.1 安装torch的CUDA版本2.1.1 查看安装的torch是什么版本2.1.2 下载GPU版本的torch 2.2 安装 NVIDIA CUDA2.2.1 下载CUDA Toolkit2.2.2 安装CUDA Toolkit 最终效果 1. 问题 在Python中&#xff0c;使用Pytorch时&#xff0c;往往会选择使用CUDA模块&a…

行业唯一!三翼鸟场景品牌战略推动价值凸显

文 | 智能相对论 作者 | 佘凯文 当你的一只羊跑进别人的羊群中&#xff0c;怎么才能找到它&#xff1f; 从前人们为了区分自己的财产&#xff0c;会用烧红的铁块印在动物身上作为标记。在中世纪的欧洲&#xff0c;手工艺匠人用这种烧灼的方法在自己的手工艺品上烙下标记&…

「Python-docx 专栏」docx 设置页面边距、页眉页脚高度

本文目录 前言一、docx 页面边距在哪里二、对 <w:pgMar> 的详细说明1、上边距的说明2、右边距的说明3、下边距的说明4、左边距的说明5、页眉高度的说明6、页脚高度的说明三、设置 docx 页边距、页眉页脚高度1、完整代码2、代码执行效果图四、补充一些内容1、页面边距的两…

[面试题]RabbitMQ

[面试题]Java【基础】[面试题]Java【虚拟机】[面试题]Java【并发】[面试题]Java【集合】[面试题]MySQL[面试题]Maven[面试题]Spring Boot[面试题]Spring Cloud[面试题]Spring MVC[面试题]Spring[面试题]MyBatis[面试题]Nginx[面试题]缓存[面试题]Redis[面试题]消息队列[面试题]…