机器人移动

This commit is contained in:
flswld
2023-05-14 18:22:52 +08:00
parent 0bc54baf12
commit 4f6a1a0825
5 changed files with 135 additions and 39 deletions

View File

@@ -54,18 +54,23 @@ type Hk4e struct {
// Hk4eRobot 原神机器人
type Hk4eRobot struct {
RegionListUrl string `toml:"region_list_url"` // 一级dispatch地址
RegionListParam string `toml:"region_list_param"` // 一级dispatch的url参数
CurRegionUrl string `toml:"cur_region_url"` // 二级dispatch地址
CurRegionParam string `toml:"cur_region_param"` // 二级dispatch的url参数
KeyId string `toml:"key_id"` // 客户端密钥编号
LoginSdkUrl string `toml:"login_sdk_url"` // sdk登录服务器地址
Account string `toml:"account"` // 帐号
Password string `toml:"password"` // base64编码的rsa公钥加密后的密码
ClientVersion string `toml:"client_version"` // 客户端版本号
DosEnable bool `toml:"dos_enable"` // 是否开启压力测试
DosNum int32 `toml:"dos_num"` // 压力测试并发数量 帐号自动添加后缀编号
DosLoopLogin bool `toml:"dos_loop_login"` // 压力测试是否循环登录退出
RegionListUrl string `toml:"region_list_url"` // 一级dispatch地址
RegionListParam string `toml:"region_list_param"` // 一级dispatch的url参数
SelectRegionIndex int32 `toml:"select_region_index"` // 选择的二级dispatch索引
CurRegionUrl string `toml:"cur_region_url"` // 二级dispatch地址 可强制指定 为空则使用一级dispatch获取的地址
CurRegionParam string `toml:"cur_region_param"` // 二级dispatch的url参数
KeyId string `toml:"key_id"` // 客户端密钥编号
LoginSdkUrl string `toml:"login_sdk_url"` // sdk登录服务器地址
Account string `toml:"account"` // 帐号
Password string `toml:"password"` // base64编码的rsa公钥加密后的密码
ClientVersion string `toml:"client_version"` // 客户端版本号
DosEnable bool `toml:"dos_enable"` // 是否开启压力测试
DosTotalNum int32 `toml:"dos_total_num"` // 压力测试总并发数量 帐号自动添加后缀编号
DosBatchNum int32 `toml:"dos_batch_num"` // 压力测试每批登录并发数量
DosLoopLogin bool `toml:"dos_loop_login"` // 压力测试是否循环登录退出
ClientMoveEnable bool `toml:"client_move_enable"` // 是否开启客户端模拟移动
ClientMoveSpeed int32 `toml:"client_move_speed"` // 客户端模拟移动速度
ClientMoveRangeExt int32 `toml:"client_move_range_ext"` // 客户端模拟移动区域半径
}
// MQ 消息队列

View File

@@ -10,7 +10,8 @@ client_proto_proxy_enable = false
[hk4e_robot]
region_list_url = "https://hk4e.flswld.com" # 一级dispatch地址
region_list_param = "" # 一级dispatch的url参数
cur_region_url = "https://hk4e.flswld.com/query_cur_region" # 二级dispatch地址
select_region_index = 0 # 选择的二级dispatch索引
cur_region_url = "https://hk4e.flswld.com/query_cur_region" # 二级dispatch地址 可强制指定 为空则使用一级dispatch获取的地址
cur_region_param = "?version=OSRELWin3.2.0&key_id=5" # 二级dispatch的url参数
key_id = "5" # 客户端密钥编号
login_sdk_url = "https://hk4e.flswld.com" # sdk登录服务器地址
@@ -18,5 +19,9 @@ account = "flswld" # 帐号
password = "" # base64编码的rsa公钥加密后的密码
client_version = "CNRELWin3.2.0_R11611027_S11212885_D11793813" # 客户端版本号
dos_enable = false # 是否开启压力测试
dos_num = 1 # 压力测试并发数量 帐号自动添加后缀编号
dos_total_num = 1 # 压力测试并发数量 帐号自动添加后缀编号
dos_batch_num = 1 # 压力测试每批登录并发数量
dos_loop_login = false # 压力测试是否循环登录退出
client_move_enable = false # 是否开启客户端模拟移动
client_move_speed = 10 # 客户端模拟移动速度
client_move_range_ext = 1024 # 客户端模拟移动区域半径

View File

@@ -3,13 +3,18 @@ package main
import (
"encoding/base64"
"encoding/hex"
"math"
"os"
"os/signal"
"strconv"
"strings"
"sync"
"syscall"
"time"
pb "google.golang.org/protobuf/proto"
"hk4e/pkg/endec"
"hk4e/pkg/random"
"hk4e/robot/net"
"hk4e/common/config"
@@ -34,12 +39,27 @@ func main() {
// engine.RunEngine([]int{0, 1, 2, 3}, 4, 1, "0.0.0.0")
// time.Sleep(time.Second * 30)
dispatchInfo, err := login.GetDispatchInfo(config.GetConfig().Hk4eRobot.RegionListUrl,
config.GetConfig().Hk4eRobot.RegionListParam,
config.GetConfig().Hk4eRobot.CurRegionUrl,
config.GetConfig().Hk4eRobot.CurRegionParam,
config.GetConfig().Hk4eRobot.KeyId)
if err != nil {
logger.Error("get dispatch info error: %v", err)
return
}
if config.GetConfig().Hk4eRobot.DosEnable {
for i := 0; i < int(config.GetConfig().Hk4eRobot.DosNum); i++ {
go httpLogin(config.GetConfig().Hk4eRobot.Account + "_" + strconv.Itoa(i))
for i := 0; i < int(config.GetConfig().Hk4eRobot.DosTotalNum); i++ {
wg := new(sync.WaitGroup)
wg.Add(int(config.GetConfig().Hk4eRobot.DosBatchNum))
for j := 0; j < int(config.GetConfig().Hk4eRobot.DosBatchNum); j++ {
go httpLogin(config.GetConfig().Hk4eRobot.Account+"_"+strconv.Itoa(i), dispatchInfo, wg)
}
wg.Wait()
}
} else {
httpLogin(config.GetConfig().Hk4eRobot.Account)
httpLogin(config.GetConfig().Hk4eRobot.Account, dispatchInfo, nil)
}
c := make(chan os.Signal, 1)
@@ -58,30 +78,28 @@ func main() {
}
}
func httpLogin(account string) {
func httpLogin(account string, dispatchInfo *login.DispatchInfo, wg *sync.WaitGroup) {
defer func() {
if config.GetConfig().Hk4eRobot.DosEnable {
wg.Done()
}
}()
logger.Info("robot start, account: %v", account)
dispatchInfo, err := login.GetDispatchInfo(config.GetConfig().Hk4eRobot.RegionListUrl,
config.GetConfig().Hk4eRobot.RegionListParam,
config.GetConfig().Hk4eRobot.CurRegionUrl,
config.GetConfig().Hk4eRobot.CurRegionParam,
config.GetConfig().Hk4eRobot.KeyId)
if err != nil {
logger.Error("get dispatch info error: %v", err)
return
}
accountInfo, err := login.AccountLogin(config.GetConfig().Hk4eRobot.LoginSdkUrl, account, config.GetConfig().Hk4eRobot.Password)
if err != nil {
logger.Error("account login error: %v", err)
return
}
for {
gateLogin(account, dispatchInfo, accountInfo)
if !config.GetConfig().Hk4eRobot.DosLoopLogin {
break
go func() {
for {
gateLogin(account, dispatchInfo, accountInfo)
if !config.GetConfig().Hk4eRobot.DosLoopLogin {
break
}
time.Sleep(time.Second)
continue
}
time.Sleep(time.Second)
continue
}
}()
}
func gateLogin(account string, dispatchInfo *login.DispatchInfo, accountInfo *login.AccountInfo) {
@@ -97,13 +115,14 @@ func gateLogin(account string, dispatchInfo *login.DispatchInfo, accountInfo *lo
logger.Error("gen clientVersionHashData error: %v", err)
return
}
checksumClientVersion := strings.Split(config.GetConfig().Hk4eRobot.ClientVersion, "_")[0]
session.SendMsg(cmd.PlayerLoginReq, &proto.PlayerLoginReq{
AccountType: 1,
SubChannelId: 1,
LanguageType: 2,
PlatformType: 3,
Checksum: "$008094416f86a051270e64eb0b405a38825",
ChecksumClientVersion: "CNRELWin3.2.0",
ChecksumClientVersion: checksumClientVersion,
ClientDataVersion: 11793813,
ClientVerisonHash: base64.StdEncoding.EncodeToString(clientVersionHashData),
ClientVersion: config.GetConfig().Hk4eRobot.ClientVersion,
@@ -116,10 +135,60 @@ func gateLogin(account string, dispatchInfo *login.DispatchInfo, accountInfo *lo
func clientLogic(account string, session *net.Session) {
ticker := time.NewTicker(time.Second)
tickCounter := uint64(0)
pingSeq := uint32(0)
enterSceneDone := false
sceneBeginTime := uint32(0)
bornPos := new(proto.Vector)
currPos := new(proto.Vector)
avatarEntityId := uint32(0)
moveRot := random.GetRandomFloat32(0.0, 359.9)
moveReliableSeq := uint32(0)
for {
select {
case <-ticker.C:
tickCounter++
if config.GetConfig().Hk4eRobot.ClientMoveEnable {
if enterSceneDone {
currPos.X -= float32(float64(config.GetConfig().Hk4eRobot.ClientMoveSpeed) * math.Sin(float64(moveRot)))
currPos.Z += float32(float64(config.GetConfig().Hk4eRobot.ClientMoveSpeed) * math.Cos(float64(moveRot)))
if currPos.X > bornPos.X+float32(config.GetConfig().Hk4eRobot.ClientMoveRangeExt) ||
currPos.Y > bornPos.Y+float32(config.GetConfig().Hk4eRobot.ClientMoveRangeExt) ||
currPos.X < bornPos.X-float32(config.GetConfig().Hk4eRobot.ClientMoveRangeExt) ||
currPos.Y < bornPos.Y-float32(config.GetConfig().Hk4eRobot.ClientMoveRangeExt) {
moveRot = random.GetRandomFloat32(0.0, 359.9)
}
moveReliableSeq += 100
entityMoveInfo := &proto.EntityMoveInfo{
EntityId: avatarEntityId,
MotionInfo: &proto.MotionInfo{
Pos: currPos,
Rot: &proto.Vector{X: 0.0, Y: moveRot, Z: 0.0},
Speed: new(proto.Vector),
State: proto.MotionState_MOTION_RUN,
RefPos: new(proto.Vector),
},
SceneTime: uint32(time.Now().UnixMilli()) - sceneBeginTime,
ReliableSeq: moveReliableSeq,
IsReliable: true,
}
combatData, err := pb.Marshal(entityMoveInfo)
if err != nil {
logger.Error("marshal EntityMoveInfo error: %v, account: %v", err, account)
continue
}
session.SendMsg(cmd.CombatInvocationsNotify, &proto.CombatInvocationsNotify{
InvokeList: []*proto.CombatInvokeEntry{{
CombatData: combatData,
ForwardType: proto.ForwardType_FORWARD_TO_ALL_EXCEPT_CUR,
ArgumentType: proto.CombatTypeArgument_ENTITY_MOVE,
}},
})
}
}
if tickCounter%5 != 0 {
continue
}
pingSeq++
// 通过这个接口发消息给服务器
session.SendMsg(cmd.PingReq, &proto.PingReq{
@@ -128,11 +197,14 @@ func clientLogic(account string, session *net.Session) {
})
case protoMsg := <-session.RecvChan:
// 从这个管道接收服务器发来的消息
logger.Debug("recv protoMsg: %v", protoMsg)
switch protoMsg.CmdId {
case cmd.PlayerLoginRsp:
rsp := protoMsg.PayloadMessage.(*proto.PlayerLoginRsp)
logger.Info("login ok, rsp: %v", rsp)
if rsp.Retcode != 0 {
logger.Error("login fail, retCode: %v, account: %v", rsp.Retcode, account)
return
}
logger.Info("login ok, account: %v", account)
case cmd.DoSetPlayerBornDataNotify:
session.SendMsg(cmd.SetPlayerBornDataReq, &proto.SetPlayerBornDataReq{
AvatarId: 10000007,
@@ -140,6 +212,8 @@ func clientLogic(account string, session *net.Session) {
})
case cmd.PlayerEnterSceneNotify:
ntf := protoMsg.PayloadMessage.(*proto.PlayerEnterSceneNotify)
bornPos.X, bornPos.Y, bornPos.Z = ntf.Pos.X, ntf.Pos.Y, ntf.Pos.Z
currPos.X, currPos.Y, currPos.Z = ntf.Pos.X, ntf.Pos.Y, ntf.Pos.Z
session.SendMsg(cmd.EnterSceneReadyReq, &proto.EnterSceneReadyReq{EnterSceneToken: ntf.EnterSceneToken})
case cmd.EnterSceneReadyRsp:
ntf := protoMsg.PayloadMessage.(*proto.EnterSceneReadyRsp)
@@ -149,10 +223,20 @@ func clientLogic(account string, session *net.Session) {
session.SendMsg(cmd.EnterSceneDoneReq, &proto.EnterSceneDoneReq{EnterSceneToken: ntf.EnterSceneToken})
case cmd.EnterSceneDoneRsp:
ntf := protoMsg.PayloadMessage.(*proto.EnterSceneDoneRsp)
enterSceneDone = true
sceneBeginTime = uint32(time.Now().UnixMilli())
session.SendMsg(cmd.PostEnterSceneReq, &proto.PostEnterSceneReq{EnterSceneToken: ntf.EnterSceneToken})
if config.GetConfig().Hk4eRobot.DosLoopLogin {
return
}
case cmd.SceneEntityAppearNotify:
ntf := protoMsg.PayloadMessage.(*proto.SceneEntityAppearNotify)
for _, sceneEntityInfo := range ntf.EntityList {
if sceneEntityInfo.EntityType != proto.ProtEntityType_PROT_ENTITY_AVATAR {
continue
}
avatarEntityId = sceneEntityInfo.EntityId
}
}
case <-session.DeadEvent:
logger.Info("robot exit, account: %v", account)

View File

@@ -61,8 +61,9 @@ func GateLogin(dispatchInfo *DispatchInfo, accountInfo *AccountInfo, keyId strin
if protoMsg.CmdId != cmd.GetPlayerTokenRsp {
return nil, errors.New("recv pkt is not GetPlayerTokenRsp")
}
// XOR密钥切换
getPlayerTokenRsp := protoMsg.PayloadMessage.(*proto.GetPlayerTokenRsp)
logger.Info("gate login ok, uid: %v", getPlayerTokenRsp.Uid)
// XOR密钥切换
seedEnc, err := base64.StdEncoding.DecodeString(getPlayerTokenRsp.ServerRandKey)
if err != nil {
logger.Error("base64 decode error: %v", err)

View File

@@ -6,6 +6,7 @@ import (
"math"
"strconv"
"hk4e/common/config"
"hk4e/common/region"
"hk4e/dispatch/api"
"hk4e/pkg/endec"
@@ -44,7 +45,7 @@ func GetDispatchInfo(regionListUrl string, regionListParam string, curRegionUrl
return nil, errors.New("no region found")
}
if curRegionUrl == "" {
selectRegion := queryRegionListHttpRsp.RegionList[0]
selectRegion := queryRegionListHttpRsp.RegionList[int(config.GetConfig().Hk4eRobot.SelectRegionIndex)]
logger.Info("select region: %v", selectRegion)
curRegionUrl = selectRegion.DispatchUrl
}