103.网络游戏逆向分析与漏洞攻防-ui界面的设计-加速功能的开关设计

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

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

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

上一个内容:102.反隐身功能的界面设计与实现(有不使用MFC生成,自己手写代码创建复选框与事件的例子)

码云版本号:825c51fa8f8a23e28088183048128102cac8b297

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

以 102.反隐身功能的界面设计与实现(有不使用MFC生成,自己手写代码创建复选框与事件的例子) 它的代码为基础进行修改

上一个内容中已经把反隐身、加速、摔不死选项做了出来,本次就把对应的功能给绑定上

效果图:加速和摔不死也实现了,但是没法用图片表示(高速移动实现:77.移动操作数据包的截取与高速移动,摔不死实现:78.屏蔽跌落数据实现摔不死和模拟原地摔死)

开启反隐身

关闭反隐身

NetClient.cpp文件的修改:修改了 OnMoveWalk函数、OnMoveStop函数、OnMoveJump函数、OnMoveWJump函数

#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  WinSock->OnSend(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 WinSock->OnSend(&_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 WinSock->OnSend(&_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 WinSock->OnSend(&_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 WinSock->OnSend((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 WinSock->OnSend(&_buff.op, ilen);}void NetClient::Teleport(float x, float h, float y, float face)
{// 修正坐标//PAIM aim = Client->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不成功,这种的可以多试几个修改坐标或者其它数据的函数如果还都不行那就没办法了*///Client->MoveWJump(v.fNan, v.fNan, v.fNan, v.fNan, v.fNan, v.fNan, v.fNan); // 可以把坐标设置成nan//Client->MoveWalk(v.fNan, v.fNan, v.fNan, v.fNan, v.fNan, v.fNan, v.fNan); // 可以把坐标设置成nanClient->MoveStop(v.fNan, v.fNan, v.fNan, v.fNan); // 可以把坐标设置成nanClient->MoveStop(x, h, y, face);// 利用修正坐标数据包瞬移Client->SetCoord(Client->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 WinSock->OnSend(&_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 WinSock->OnSend(&_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 WinSock->OnSend(&_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 WinSock->OnSend(&_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 WinSock->OnSend(&_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::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 WinSock->OnSend(&_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 WinSock->OnSend(&_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 WinSock->OnSend(&_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 WinSock->OnSend(&_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 WinSock->OnSend(&_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 WinSock->OnSend((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();}}
}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(GameWinSock* _winSock)
{for (int i = 0; i < 0x100; i++) {SendProc[i] = &NetClient::DefaultProc;RecvProc[i] = &NetClient::DefaultProc;}this->WinSock = _winSock;// 注册登录数据包处理函数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;
}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 WinSock->Recv(&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 WinSock->Recv(&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  WinSock->OnSend(buff, sizeof(buff));*/
}bool NetClient::OnStartCreateRole(int code)
{return true;
}bool NetClient::OnCreateRole(PNS_CREATEROLE _header, PCREATE_ROLE_DATAS _body)
{return true;
}bool NetClient::OnSendCustom(PNET_SEND_CHEAD _coder, char*& buffer, unsigned& len)
{switch (_coder->opcode.value()){case SC_CHOOSECAMP:return OnChooseCamp((PNS_CHOOSECAMP)_coder);case SC_CHAT:return OnChat((PCHAT_DATA)_coder);case SC_BEEP:return OnHeartBeep((PHEART_BEEP)_coder);case SC_LOOP:return OnHeartLoop((PHEART_LOOP)_coder);case SC_INITED:return OnInited();case SC_REONLINE://case SC_INIT_START://case SC_HAND://case SC_HAND_IN://    return false;case SC_MOVE_HEADER:return OnMove((PMOVE_DATA)_coder);case SC_FALL_HEADER:return OnFall((PFALL_DATA_START)_coder);case SC_INWATER:return false;case SC_USESKILL:return OnUseSkill((PUSESKILL)_coder);default:return true;}return true;
}bool NetClient::OnSelectRole(wchar_t* rolename)
{//AfxMessageBox(rolename);return true;
}bool NetClient::OnChooseCamp(PNS_CHOOSECAMP _coder)
{PNS_CHOOSECAMP _p = (PNS_CHOOSECAMP)_coder;return true;
}bool NetClient::OnChat(PCHAT_DATA _coder)
{switch (_coder->ChartId){case 3:// 私聊return OnChatPrivate((PCHAT_PRV)_coder);case 1:// 附近频道case 2:// 区域频道case 6:// 公会频道case 9:// 阵营频道case 21:// 喊话频道return OnChatPublic((PCHAT_PUB)_coder);break;}return true;
}bool NetClient::OnChatPublic(PCHAT_PUB _coder)
{return true;
}bool NetClient::OnChatPrivate(PCHAT_PRV _coder)
{return true;
}bool NetClient::OnHeartBeep(PHEART_BEEP _coder)
{return true; // 返回false会拦截81心跳包不给服务端发送
}bool NetClient::OnHeartLoop(PHEART_LOOP _coder)
{return true; // 返回false会拦截SC_LOOP心跳包不给服务端发送
}bool NetClient::OnMove(PMOVE_DATA _coder)
{switch (_coder->Mode){case 0:return OnMoveStop((PMOVE_DATA_STOP)_coder);case 1:return OnMoveWalk((PMOVE_DATA_WALK)_coder);case 2:return OnMoveJump((PMOVE_DATA_JUMP)_coder);case 3:return OnMoveWJump((PMOVE_DATA_WJUMP)_coder);}return false;
}// 移动中处理函数
bool NetClient::OnMoveWalk(PMOVE_DATA_WALK _coder)
{/*float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;MoveSpeed[0] = 5.0f;*//*if (HideMode) {float* f = (float*)_coder->h.oldPointer;f[0] = f[0] + 5;}*/return true;
}// 停止移动处理函数
bool NetClient::OnMoveStop(PMOVE_DATA_STOP _coder)
{/*  if (HideMode) {float* f = (float*)_coder->h.oldPointer;f[0] = f[0] + 5;}*/return true;
}// 跳跃处理函数
bool NetClient::OnMoveJump(PMOVE_DATA_JUMP _coder)
{//float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;//MoveSpeed[0] = 5.0f;//if(HideMode) {//    float* f = (float*)_coder->h.oldPointer;//    f[0] = f[0] + 5;//}return true;
}// 移动时跳跃
bool NetClient::OnMoveWJump(PMOVE_DATA_WJUMP _coder)
{/* float* MoveSpeed = (float*)_coder->MoveSpeed.oldPointer;MoveSpeed[0] = 5.0f;*///if(HideMode) {//    float* f = (float*)_coder->h.oldPointer;//    f[0] = f[0] + 5;//}return true;
}bool NetClient::OnFall(PFALL_DATA_START _coder)
{return true;
}bool NetClient::OnSvrChat(PCHAT_PRV _coder)
{//AfxMessageBox(_coder->name);//AfxMessageBox(_coder->txt);//switch (_coder->ChartId)//{//case 3:// 私聊//    return OnChatPrivate((PCHAT_PRV)_coder);//case 1:// 附近频道//case 2:// 区域频道//case 6:// 公会频道//case 9:// 阵营频道//case 21:// 喊话频道//    return OnChatPublic((PCHAT_PUB)_coder);//    break;//}return true;
}bool NetClient::OnUseSkill(PUSESKILL _coder)
{// 无法x坐标无效,会无法释放技能/*float* f = (float*)_coder->x.oldPointer;f[0] = 0;*/return true;
}bool NetClient::OnInited()
{return true;
}bool NetClient::Tips(int code)
{
#ifdef  AnlyCString txt;if (code == 51001) {txt = L"登陆失败,易道云通行证不存在!";}else if (code == 51002) {txt = L"登录失败,密码错误!";}else if (code == 21101) {txt = L"人物重名!";}else if (code == 21109) {txt = L"名字过长或包含非法字符!";}else {txt.Format(L"未知登录错误:%d", code);}anly->SendData(TTYPE::I_LOG, 0, txt.GetBuffer(), (txt.GetLength() + 1)*2);
#endifreturn true;
}void NetClient::loginok(ROLE_DATA* _roles, int count)
{logined = true;if(roles) delete[] roles;roles = _roles;rolecount = count;
}bool NetClient::OnScrStartCreateRole(short code, wchar_t* _txt)
{return true;
}bool NetClient::OnSvrNotice(PNET_SEND_CHEAD _coder, int count, char*& buffer, unsigned& len)
{if (_coder->msgHeader == "chat") {return OnSvrChat((PCHAT_PRV)_coder);}return true;
}bool NetClient::OnRecvData(char*& buff, unsigned& len)
{
#ifdef  Anlyanly->SendData(TTYPE::I_RECV, buff[0], buff, len);
#endifreturn (this->*RecvProc[buff[0]])(buff, len);
}bool NetClient::OnSendData(char*& buff, unsigned& len)
{
#ifdef  Anlyanly->SendData(TTYPE::I_SEND, buff[0], buff, len);
#endifreturn (this->*SendProc[buff[0]])(buff, len);
}bool NetClient::OnConnect(char*& ip, unsigned& port)
{
#ifdef  Anly// 长度24的原因,它是宽字节要,一个文字要2个字节,一共是10个文字加上结尾的0是11个// 所以 11 乘以2,然后再加2 anly->SendData(TTYPE::I_LOG, 0, L"服务器正在连接。。。", 24);
#endifreturn true;
}// 默认的数据处理函数
bool NetClient::DefaultProc(char*&, unsigned&)
{return true;
}// 复制过来的内容
bool NetClient::OnClientlogin(char*& buff, unsigned& len)
{PDATALOGIN _data = (PDATALOGIN)(buff + 1);char* _id = _data->Id;_data = (PDATALOGIN)(buff + 1 + _data->lenId - 0x10);char* _pass = _data->Pass;Onlogin(_id, _pass);/* 修改账号密码len = sizeof(DATA_LOGIN) + 1;buff = new char[len];DATA_LOGIN data;PDATALOGIN _data = &data;buff[0] = 0x2;CStringA _id = "";// 补充账号CStringA _pass = "";// 补充密码memcpy(_data->Id, _id.GetBuffer(), _id.GetLength());memcpy(_data->Pass, _pass.GetBuffer(), _pass.GetLength());memcpy(buff + 1, _data, len - 1);*//* 监控登录数据PDATALOGIN _data = (PDATALOGIN)buff;CStringA _id = _data->Id;_data = (PDATALOGIN)(buff + _data->lenId - 0x10);CStringA _pass = _data->Pass;CStringA _tmp;// 请求登录 账号[% s]密码[% s] 这个内容别人在逆向的时候就会看到// 所以这种东西需要自己搞个编码来代替它_tmp.Format("请求登录 账号[%s]密码[%s]", _id, _pass);
#ifdef  Anlyanly->SendData(TTYPE::I_DIS, 1, _tmp.GetBuffer(), _tmp.GetAllocLength());
#endif*//*返回false,游戏无法发送数据包原因看调用此此函数的位置 OnSend 函数(if (SendDealProc[buff[0]]((buff + 1), len - 1)))*/return true;
}bool NetClient::OnClientStartCreateRole(char*& buff, unsigned& len)
{// 申请进入创建角色界面int* code = (int*)&buff[1];return OnStartCreateRole(code[0]);
}bool NetClient::OnClientCreateRole(char*& buff, unsigned& len) {PNS_CREATEROLE head = (PNS_CREATEROLE)(buff - 3);int icount = head->count;if (icount < 1)return true;char* buffStart = (char*)head + sizeof(NET_SEHD_CREATEROLE_HEAD);
#ifdef AnlyGameAnlyer->AnlyBuff(buffStart, buff + len, buff[0], 1);// 翻译解析约定数据
#endif // AnlyEnCode codes[sizeof(CREATE_ROLE_DATAS) / sizeof(EnCode)]{};int stDecode = 0;while (stDecode < icount) {codes[stDecode++] = buffStart;}/*Client->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;}/*Client->OnSendCustom((PNET_SEND_CHEAD)codes, buff, len); 数据包传给虚函数如果想对发送数据的0A开头的据包做些什么直接继承NetClient重写OnSendCustom函数既可以了*/return Client->OnSendCustom((PNET_SEND_CHEAD)codes, buff, len);}bool NetClient::OnClientSelectRole(char*& buff, unsigned& len) {PNS_SELECTROLE p = (PNS_SELECTROLE)buff;return Client->OnSelectRole((wchar_t*)(p->buff));
}bool NetClient::OnClientDelRole(char*& buff, unsigned& len) {PDATADELROLE p = (PDATADELROLE)buff;return Client->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 Client->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);}Client->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);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;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];}#ifdef AnlyGameAnlyer->CreateStructfile(StructTable, head->count);
#endif // Anlyreturn 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);PAIM _paim = GetAimById(head->lId);int iref = 0;short refcount = head->icount;
#ifdef  Anlychar* buffStart = (char*)&head->itype;GameAnlyer->AnlyData(buffStart, buff + len, refcount, S_UPDATEPRO, ObjectTable);
#endifwhile (iref < refcount) {_paim->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);
#endif/* int iProc = 0;while (iProc < head->icount){Player.UpdateData(buffStart);iProc++;}*/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 Client->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/*Client->OnSendCustom((PNET_SEND_CHEAD)codes, buff, len); 数据包传给虚函数如果想对0A开头的据包做些什么直接继承NetClient重写OnSendCustom函数既可以了*/return Client->OnScrStartCreateRole(_st[0], _txt);
}

CWndSet.cpp文件的修改:新加 _wndSet变量,修改了 CWndSet函数、OnSet函数

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

CWndSet.h文件的修改:新加 setValue变量、OldSpeed变量、SetSpeed变量

#pragma once
#include "afxdialogex.h"
#include "CWndCreateRole.h"#define IDC_SETBASE (WM_USER + 100)// 处理按钮的消息映射
// CWndSet 对话框
enum class SETNAME {AntiHide, // 隐身AddSpeed, // 加速NeverFall, // 摔不死MAX
};
class CWndSet : public CDialogEx
{DECLARE_DYNAMIC(CWndSet)public:CWndSet(CWnd* pParent = nullptr);   // 标准构造函数virtual ~CWndSet();// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_PAGE_2 };
#endifCString txtName[(unsigned)SETNAME::MAX]{L"反隐身",L"加速",L"摔不死",};CButton setButton[(unsigned)SETNAME::MAX];// 复选框bool setValue[(unsigned)SETNAME::MAX]{}; // 用来获取复选框是否选中的float OldSpeed;// 原本的移动速度float SetSpeed = 50.0f; // 修改移动速度
protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持virtual BOOL OnInitDialog();DECLARE_MESSAGE_MAP()afx_msg void OnSet(UINT i);
};

extern_all.h文件的修改:新加 _wndSet变量

/*此文件是用来存放全局变量、全局函数(通用函数)
*/
#pragma once
#include "GameWinSock.h"
#include "GameProc.h"
#include "CAnly.h"
#include "NetClient.h"
#include "GameAnly.h"
#include "TextManger.h"
#include "CWndSet.h"typedef struct DATA_DESC {char* name;short lenth;
}*PDATADESC;extern 	GameWinSock* WinSock;
extern GameProc* PGameProc;
extern NetClient* Client;
extern DATA_DESC data_desc[3][10];
extern void InitClassProc(LPVOID proc_addr, unsigned value);
extern void init_datadesc();extern PTextManger txtManger;class GameAnly; // 不加这一个会因为引用编译不通过
#ifdef Anly
extern CAnly* anly;
extern GameAnly* GameAnlyer;
#endifextern CWndSet* _wndSet;

CUI.cpp文件的修改:重写 OnFall函数、OnMoveWalk函数、OnMoveJump函数、OnMoveWJump函数

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

CUI.h文件的修改:重写 OnFall函数、OnMoveWalk函数、OnMoveJump函数、OnMoveWJump函数

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

AIM.cpp文件的修改: 重写SetMoveSpeed函数

#include "pch.h"
#include "AIM.h"
#include "extern_all.h"// 复制游戏数据包到自己的内存中
// Create是预留的一个接口暂时没用到
void AIM::SetHeadDatas(void* buffStart, bool Create)
{Isfree = false;unsigned lStart = (unsigned)&lId;unsigned lEnd = (unsigned)&endclass;memcpy(&lId, buffStart, lEnd - lStart);
}bool AIM::SetHeadCord(void* buffStart)
{Isfree = false;unsigned lStart = (unsigned)&lId;unsigned lEnd = (unsigned)&tx;memcpy(&lId, buffStart, lEnd - lStart);return true;
}// 怪物只有ConfigId没有名字,所以重写SetConfigID让它根据ConfigId获取中文名
void AIM::SetConfigID(char*& buffStart)
{GAMEOBJECT::SetConfigID(buffStart);Name = txtManger->ReadTextById(ConfigID);
}void AIM::SetRoleHide(char*& buffStart)
{// 下方的判断是用来判断当前属性的更新是否是我们玩家自己// this->lId == Client->Player.lId;int* ntRead = (int*)buffStart;int value = ntRead[0];if(_wndSet->setValue[(unsigned)SETNAME::AntiHide])ntRead[0] = 0;GAMEOBJECT::SetRoleHide(buffStart);RoleHide = value;
}void AIM::SetMoveSpeed(char*& buffStart)
{// SetMoveSpeed是设置移动速度float* read = (float*)buffStart;if(read[0] < _wndSet->SetSpeed)_wndSet->OldSpeed = read[0];if (_wndSet->setValue[(unsigned)SETNAME::AddSpeed]) {read[0] = _wndSet->SetSpeed;}GAMEOBJECT::SetMoveSpeed(buffStart);
}

AIM.h文件的修改: 重写SetMoveSpeed函数

#pragma once
#include "GameOBJECT.h"
typedef class AIM:public GAMEOBJECT {
public:long long lId;float x;float h;float y;float face;float tx;float th;float ty;float tface;int IState;int endclass;// Create是预留的一个接口暂时没用到void virtual SetHeadDatas(void* buffStart, bool Create = true);bool virtual SetHeadCord(void* buffStart);// 怪物只有ConfigId没有名字,所以重写SetConfigID让它根据ConfigId获取中文名void virtual SetConfigID(char*& buffStart); // 设置ConfigIdvoid virtual SetRoleHide(char*& buffStart); // 设置角色显示隐藏void virtual SetMoveSpeed(char*& buffStart);// 设置移动速度
}*PAIM;

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

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

相关文章

李廉洋:6.4-6.5黄金原油再次走低,美盘行情分析及最新策略。

黄金消息面分析&#xff1a;全球债券周二上涨&#xff0c;呼应美债隔夜的涨势。美联储或早降息的押注增强了主权债务的吸引力。澳大利亚和新西兰10年期债券收益率下跌至少8个基点&#xff0c;先前数据显示&#xff0c;美国5月份工厂活动萎缩的速度加快。日本10年期债券收益率下…

Nginx location 与 Rewrite

Nginx正则表达式 location 通过前缀或正则匹配用户的URL访问路径做页面跳转、访问控制和代理转发 location 大致可以分为三类&#xff1a; 精准匹配&#xff1a;location / {...} 一般匹配&#xff1a;location / {...} 正则匹配&#xff1a;location ~ / {...} location…

ctfshow解题,知识点学习

1.easy_zip&#xff08;misc&#xff09; 1&#xff09;打开环境后是一个压缩包&#xff0c;解压里面有个flag.txt文件需要密码&#xff0c; 2&#xff09;直接用工具爆破&#xff0c;即可找到密码 2.easy_eval 1&#xff09;进入题目环境&#xff0c;先进行代码审计 首先说是…

让你的博客实现负载均衡

零、缘起 有时候博客突然挂了&#xff0c;发现服务器厂商出了问题&#xff0c;很忧伤&#xff0c;我正在写着或查阅自家博客那种不可xx的内容。这时想着&#xff0c;如果这个博客有负载均衡就好了&#xff0c;空了想着实现下。 一分钟了解负载均衡的一切 选择第二种【反向代…

MoE 大模型的前世今生

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学。 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 合集&#x…

Vue3整合Tailwindcss之padding样式类

04 常用基础样式 padding 样式类 什么是内边距 基础样式 ClassPropertiesp-0padding: 0px;px-0padding-left: 0px; padding-right: 0px;py-0padding-top: 0px; padding-bottom: 0px;ps-0padding-inline-start: 0px;pe-0padding-inline-end: 0px;pt-0padding-top: 0px;pr-0pa…

kafka-生产者监听器(SpringBoot整合Kafka)

文章目录 1、生产者监听器1.1、创建生产者监听器1.2、发送消息测试1.3、使用Java代码创建主题分区副本1.4、application.yml配置----v1版1.5、屏蔽 kafka debug 日志 logback.xml1.6、引入spring-kafka依赖1.7、控制台日志 1、生产者监听器 1.1、创建生产者监听器 package co…

图片批量纵向拼接神器:轻松插入间隔像素,生成真彩绚丽长图,让你的创意无限延伸!

在数字艺术的世界里&#xff0c;图片拼接早已不再是简单的组合&#xff0c;而是创意与技术的融合。如果你正在寻找一款能够快速将图片进行纵向拼接&#xff0c;并且能轻松插入间隔像素&#xff0c;同时保证色彩绚丽的神器&#xff0c;那么&#xff0c;我们首助编辑高手的长图拼…

如何实现单例模式及不同实现方法分析-设计模式

这是 一道面试常考题&#xff1a;&#xff08;经常会在面试中让手写一下&#xff09; 什么是单例模式 【问什么是单例模式时&#xff0c;不要答非所问&#xff0c;给出单例模式有两种类型之类的回答&#xff0c;要围绕单例模式的定义去展开。】 单例模式是指在内存中只会创建…

React 中的 ForwardRef的使用

React 中的 forwardRef Hooks 是指将子组件的 Dom 节点暴露给给父组件&#xff0c;在 React 中如果想要访问 Dom 节点是通过 useRef 这个 hooks&#xff0c;而 forwardHook 在 useRef 做了扩展。useRef 是当前组件中间中的节点&#xff0c;而 forwardRef 相当于做了一层封装将父…

springAOP 使用aop代替SqlsessionUtil业务层操作

在Maven框架pom配置文件中导入spring相关依赖&#xff1a; <dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency…

mac配置Personal Access Tokens

背景 在macbook环境中&#xff0c;使用idea、android studio、xcode时&#xff0c;使用gitlab需要登录&#xff0c;而直接使用文明密码是不允许登录的&#xff0c;这时就需要换种方式&#xff0c;这里有两种&#xff1a;ssh、Access Tokens&#xff0c;在公用电脑上推荐使用Ac…

第一个SpringBoot项目

目录 &#x1f4ad;1、新建New Project IDEA2023版本创建Sping项目只能勾选17和21&#xff0c;却无法使用Java8&#xff1f;&#x1f31f; 2、下载JDK 17&#x1f31f; &#x1f4ad;2、项目创建成功界面 1、目录 &#x1f31f; 2、pom文件&#x1f31f; &#x1f4ad;3、…

【数据分享】中国民政统计年鉴(1949-2022)

大家好&#xff01;今天我要向大家介绍一份重要的中国民政统计数据资源——《中国民政统计年鉴》。这份年鉴涵盖了从1949年到2022年中国民政统计全面数据&#xff0c;并提供限时免费下载。&#xff08;无需分享朋友圈即可获取&#xff09; 数据介绍 从1949年到2022年&#xf…

云原生架构案例分析_4.某电商业务云原生改造

名称解释&#xff1a; AHAS&#xff1a;应用高可用服务&#xff08;Application High Availability Service&#xff09;是一款专注于提高应用高可用能力的SaaS产品&#xff0c;主要包含多活容灾、故障演练和流量防护三个独立的功能模块。其中流量防护已迁移至微服务治理服务MS…

再度“冲三”失利的泸州老窖,还能拿出什么“杀手锏”?

正值“618”&#xff0c;白酒行业也迎来了重要创收时刻。 据悉&#xff0c;天猫“618购物节”开卖首日&#xff0c;酒水直播销售额增长超1300%&#xff0c;拉动白酒行业增长147%。 这一增长背后&#xff0c;赛道的火药味也愈发浓厚&#xff0c;今年618大促中&#xff0c;五粮…

【电路笔记】-Sallen-Key滤波器

Sallen-Key滤波器 Sallen-Key 滤波器拓扑用作实现高阶有源滤波器的构建块。 1、概述 Sallen-Key 滤波器设计是一种二阶有源滤波器拓扑,我们可以将其用作实现高阶滤波器电路的基本构建块,例如低通 (LPF)、高通 (HPF) 和带通 ( BPF)滤波器电路。 正如我们在本滤波器部分中…

【匹配线段问题】

问题&#xff1a; 如下图所示。图中有两行正整数&#xff0c;每行中有若干个正整数。如果第一行的某个数r与第二行的某个数相同&#xff0c;这样就可以在这两个正整数之间划一条线&#xff0c;并称之为r-匹配线段。下图中存在3-匹配线段和2-匹配线段。 请编写完整程序&#xf…

【C语言】详解函数(庖丁解牛版)

文章目录 1. 前言2. 函数的概念3.库函数3.1 标准库和头文件3.2 库函数的使用3.2.1 头文件的包含3.2.2 实践 4. 自定义函数4.1 自定义函数的语法形式4.2 函数的举例 5. 形参和实参5.1 实参5.2 形参5.3 实参和形参的关系 6. return 语句6. 总结 1. 前言 一讲到函数这块&#xff…

数字塔问题

#include<iostream> using namespace std; //从下向上得到最优值 void dtower(int a[][100],int s[][100],int n) {for(int in; i>1; i--){for(int j1; j<i; j){if(in)s[i][j]a[i][j];else{int ts[i1][j];if(t<s[i1][j1])ts[i1][j1];s[i][j]a[i][j]t;}}} } void…