role_state.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. package model
  2. import (
  3. "math/rand"
  4. "rocommon"
  5. "rocommon/service"
  6. "rocommon/util"
  7. "roserver/baseserver"
  8. "roserver/baseserver/model"
  9. "roserver/serverproto"
  10. "runtime/debug"
  11. "time"
  12. "unsafe"
  13. )
  14. //状态机枚举
  15. const (
  16. ROLE_STATE_ONLINE = 1 //在线
  17. ROLE_STATE_OFFLINE = 2 //离线
  18. ROLE_STATE_PULLING_LIST = 3 //拉取角色信息
  19. ROLE_STATE_PULLED_LIST = 4 //拉去角色列表完成(从db返回信息)
  20. ROLE_STATE_CREATE = 5 //正在创建角色
  21. ROLE_STATE_CREATE_SUCCESS = 6 //创建角色成功
  22. ROLE_STATE_CREATE_FAILURE = 7 //创建角色失败
  23. ROLE_STATE_DB_ADD_ROLE_SUCCESS = 8 //数据库添加角色信息成功
  24. ROLE_STATE_DB_ADD_ROLE_FAILURE = 9 //数据库添加角色信息失败
  25. ROLE_STATE_SELECT_ROLE = 10
  26. ROLE_STATE_SELECT_ROLE_SUCCESS = 11 //选择角色成功
  27. ROLE_STATE_SELECT_ROLE_FAILURE = 12 //选择角色失败
  28. ROLE_STATE_ZOMBIE = 13
  29. )
  30. //状态机执行信息
  31. //拉取角色信息
  32. var pullingRoleList = func(r *model.StateMachineCore, data interface{}) int32 {
  33. parent := unsafe.Pointer(r)
  34. return (*Role)(parent).pullingRoleList()
  35. //return ROLE_STATE_PULLING_LIST
  36. }
  37. var pulledRoleList = func(r *model.StateMachineCore, data interface{}) int32 {
  38. parent := unsafe.Pointer(r)
  39. return (*Role)(parent).pulledRoleList()
  40. //return ROLE_STATE_PULLED_LIST
  41. }
  42. var createRole = func(r *model.StateMachineCore, data interface{}) int32 {
  43. parent := unsafe.Pointer(r)
  44. return (*Role)(parent).createRole()
  45. //return ROLE_STATE_CREATE
  46. }
  47. var createDbRoleSuccess = func(r *model.StateMachineCore, data interface{}) int32 {
  48. parent := unsafe.Pointer(r)
  49. return (*Role)(parent).createDbRoleSuccess()
  50. //return ROLE_STATE_DB_ADD_ROLE_SUCCESS
  51. }
  52. var createDbRoleFailure = func(r *model.StateMachineCore, data interface{}) int32 {
  53. parent := unsafe.Pointer(r)
  54. return (*Role)(parent).createDbRoleFailure(data)
  55. //return ROLE_STATE_DB_ADD_ROLE_FAILURE
  56. }
  57. var SelectingRole = func(r *model.StateMachineCore, data interface{}) int32 {
  58. parent := unsafe.Pointer(r)
  59. return (*Role)(parent).SelectingRole()
  60. //return ROLE_STATE_SELECT_ROLE
  61. }
  62. var SelectRoleSuccess = func(r *model.StateMachineCore, data interface{}) int32 {
  63. parent := unsafe.Pointer(r)
  64. return (*Role)(parent).SelectRoleSuccess()
  65. //return ROLE_STATE_SELECT_ROLE_SUCCESS
  66. }
  67. var RoleOnline = func(r *model.StateMachineCore, data interface{}) int32 {
  68. parent := unsafe.Pointer(r)
  69. return (*Role)(parent).RoleOnline(data)
  70. }
  71. var RoleOffline = func(r *model.StateMachineCore, data interface{}) int32 {
  72. parent := unsafe.Pointer(r)
  73. return (*Role)(parent).RoleOffline()
  74. //return ROLE_STATE_OFFLINE
  75. }
  76. func (this *Role) pullingRoleList() int32 {
  77. util.DebugF("pullingRoleList... %v,%v", this.cliID, this.UuidList)
  78. //选择DB节点
  79. this.dbNode = model.SelectServiceNode(model.SERVICE_NODE_TYPE_DB_STR, 0)
  80. this.setUUid(0) //获取成功后会再次赋值
  81. //发送获取角色信息消息给db服务器
  82. msg := &serverproto.SSAccountGetRoleListReq{
  83. ChannelId: this.cliID.SessID,
  84. OpenId: this.openId,
  85. //ZoneId: int32(service.GetServiceConfig().Node.Zone),
  86. }
  87. //使用服务器选择的服务器使用
  88. if this.selectZone > 0 {
  89. msg.ZoneId = this.selectZone
  90. } else {
  91. msg.ZoneId = int32(service.GetServiceConfig().Node.Zone)
  92. }
  93. ret := this.SendDb(msg)
  94. if !ret {
  95. ackMsg := &serverproto.SCLoginAck{
  96. Error: int32(serverproto.ErrorCode_ERROR_FAIL),
  97. }
  98. this.ReplayGate(ackMsg, true)
  99. return ROLE_STATE_ZOMBIE
  100. }
  101. return ROLE_STATE_PULLING_LIST
  102. }
  103. func (this *Role) pulledRoleList() int32 {
  104. util.DebugF("pulledRoleList... %v,%v", this.cliID, this.UuidList)
  105. //角色信息不存在则创建角色信息
  106. if len(this.UuidList) <= 0 {
  107. if service.GetServiceConfig().Node.RobotMode == 2 {
  108. this.LoginAck(serverproto.ErrorCode_ERROR_ROLE_CAN_NOT_REGISTER)
  109. return ROLE_STATE_ZOMBIE
  110. } else {
  111. if service.GetServiceConfig().Node.AuthMode == AUTHMODE_ACTIVE {
  112. this.LoginAck(serverproto.ErrorCode_ERROR_ROLE_NOT_FOUND_NEED_ACTIVE_CODE)
  113. } else {
  114. this.LoginAck(serverproto.ErrorCode_ERROR_ROLE_NOT_FOUND)
  115. }
  116. }
  117. return ROLE_STATE_PULLED_LIST
  118. } else {
  119. //默认选择第一个,如果后续做成多角色系统,由客户端发起选择操作
  120. this.SetSelectUUid(this.UuidList[0])
  121. //this.SwitchState(ROLE_STATE_SELECT_ROLE, nil)
  122. return ROLE_STATE_SELECT_ROLE
  123. }
  124. }
  125. func (this *Role) createRole() int32 {
  126. this.setUUid(model.GenerateUidByZone(int(this.GetSelectZone())))
  127. //生成唯一索引ID失败
  128. if this.GetUUid() <= 0 {
  129. msg := &serverproto.SCCreateRoleAck{
  130. Error: int32(serverproto.ErrorCode_ERROR_FAIL),
  131. }
  132. util.InfoF("createRole err uid invalid!!!")
  133. this.ReplayGate(msg, true)
  134. return ROLE_STATE_CREATE_FAILURE
  135. }
  136. RoleMag.Resolve(this)
  137. data := this.base.roleBase
  138. msg := &serverproto.SSAddRoleBaseReq{}
  139. //初始化创建角色数据
  140. msg.Base = &serverproto.RoleBase{
  141. Id: this.uuid,
  142. Coin: 0, //默认值通过配置表处理
  143. Rmb: 0,
  144. NickName: "",
  145. Sex: data.Sex,
  146. Country: data.Country,
  147. GuideId: 0,
  148. RoleData: &serverproto.RoleData{
  149. HeroData: &serverproto.HeroData{
  150. Id: 1,
  151. BaseLevel: 1,
  152. ConfigId: data.RoleData.HeroData.ConfigId,
  153. IsBattle: true,
  154. Skill: &serverproto.RoleSkill{},
  155. Slot: &serverproto.SlotData{
  156. HeroId: 1,
  157. },
  158. SkillEquipSlot: &serverproto.SkillEquipSlotData{
  159. HeroId: 1,
  160. },
  161. },
  162. },
  163. FashionData: data.FashionData,
  164. }
  165. //激活码
  166. msg.ActiveCode = this.activeCode
  167. msg.OpenId = this.GetOpenId()
  168. msg.SubPlatform = this.GetSubPlatform()
  169. msg.Zone = this.GetSelectZone()
  170. this.SendDb(msg)
  171. return ROLE_STATE_CREATE
  172. }
  173. type OpenIdServeNode struct {
  174. ServerId int32
  175. HeadFrameId int32
  176. Level int32
  177. JobCfgId int32
  178. Gender int32
  179. NickName string
  180. }
  181. func (this *Role) createDbRoleSuccess() int32 {
  182. //todo...流程上有问题,这边需要返回成功才能做后续操作
  183. //角色基本信息添加成功后再添加到openId对应的玩家列表中(多角色登录处理)
  184. msg := &serverproto.SSAccountAddRoleNtf{}
  185. accRole := &serverproto.AccountRole{}
  186. accRole.Uid = this.GetUUid()
  187. accRole.OpenId = this.GetOpenId()
  188. accRole.RegisterTime = util.GetTimeMilliseconds()
  189. if this.GetSelectZone() > 0 {
  190. accRole.ZoneId = this.GetSelectZone()
  191. } else {
  192. accRole.ZoneId = int32(service.GetServiceConfig().Node.Zone)
  193. }
  194. msg.Roles = append(msg.Roles, accRole)
  195. util.DebugF("uid=%v SSAccountAddRoleNtf send to db ", accRole.Uid)
  196. this.SendDb(msg)
  197. //todo...
  198. // 默认选择创建的角色,后续做成多角色的话需要客户端发起选择角色操作
  199. // 注意以后合区操作
  200. this.UuidList = append(this.UuidList, this.GetUUid())
  201. this.UuidRoleList[this.GetUUid()] = accRole
  202. this.SetSelectUUid(this.GetUUid())
  203. this.setUUid(this.GetUUid())
  204. //创建角色成功后发送给roweb服务器记录当前openID登录的服务器信息
  205. this.registerServerList(0, 1)
  206. //创建角色成功,发送给客户端用户sdk处理
  207. createMsg := &serverproto.SCCreateRoleAck{
  208. Error: int32(serverproto.ErrorCode_ERROR_OK),
  209. CreateRoleTime: accRole.RegisterTime,
  210. Uid: accRole.Uid,
  211. Gender: this.GetRoleBase().GetRoleSex(),
  212. }
  213. this.ReplayGate(createMsg, true)
  214. this.roleTask.AddTypeCnt(serverproto.TaskType_Eve_Login_Day, 1)
  215. return ROLE_STATE_SELECT_ROLE
  216. }
  217. func (this *Role) createDbRoleFailure(data interface{}) int32 {
  218. msg := &serverproto.SCCreateRoleAck{}
  219. //msg.Error = data.(int32)
  220. msg.Error = int32(serverproto.ErrorCode_ERROR_FAIL)
  221. //log.Println("[createDbRoleFailure]")
  222. util.InfoF("createDbRoleFailure")
  223. this.ReplayGate(msg, true)
  224. return ROLE_STATE_CREATE_FAILURE
  225. }
  226. func (this *Role) SelectingRole() int32 {
  227. //检查合法性
  228. valid := false
  229. for _, data := range this.UuidList {
  230. if data == this.SelectedUuid {
  231. valid = true
  232. break
  233. }
  234. }
  235. if !valid {
  236. this.LoginAck(serverproto.ErrorCode_ERROR_FAIL)
  237. util.InfoF("select role not found uuid=%v", this.SelectedUuid)
  238. return ROLE_STATE_ZOMBIE
  239. }
  240. this.setUUid(this.SelectedUuid)
  241. return ROLE_STATE_SELECT_ROLE_SUCCESS
  242. }
  243. func (this *Role) SelectRoleSuccess() int32 {
  244. //非创建流程时,此时才获得角色的uuid
  245. RoleMag.Resolve(this)
  246. //缓存数据处理
  247. if !this.reLogin {
  248. //获取角色信息其他信息
  249. msg := &serverproto.SSGetRoleReq{
  250. RoleRegisterTime: this.RegisterTime,
  251. }
  252. this.SendDb(msg)
  253. } else {
  254. //数据在缓存中,直接切换成在线状态
  255. //this.LoginAck(serverproto.ErrorCode_ERROR_OK)
  256. return ROLE_STATE_ONLINE
  257. }
  258. return ROLE_STATE_SELECT_ROLE_SUCCESS
  259. }
  260. func (this *Role) RoleOnline(data interface{}) int32 {
  261. if !this.isLoad {
  262. this.KickNotSave(int32(serverproto.ErrorCode_ERROR_FAIL))
  263. return ROLE_STATE_ZOMBIE
  264. }
  265. //be baned by webgm
  266. banTime := this.isBan()
  267. if banTime > 0 {
  268. this.LoginAck(serverproto.ErrorCode_ERROR_ROLE_BANED)
  269. this.KickWithSaveAndBan(int32(serverproto.ErrorCode_ERROR_ROLE_BANED), banTime)
  270. return ROLE_STATE_ZOMBIE
  271. }
  272. this.LoginAck(serverproto.ErrorCode_ERROR_OK)
  273. this.tmpState = true
  274. //每日5点重置
  275. if this.isDailyReset() {
  276. this.DailyReset(false)
  277. }
  278. this.GetRoleBase().SetLastLoginTime()
  279. //记录最近在线玩家列表
  280. RoleMag.AddFIFOList(this.GetUUid())
  281. //如果是从离线池中获取,停止离线定时器
  282. this.offlineTimer.Cancel()
  283. //启动数据保存定时器
  284. nowTime := util.GetTimeMilliseconds()
  285. this.saveTimer.Reset(nowTime, roleSaveTimeout, false)
  286. this.mysqlLogSaveTimer.Reset(nowTime, mysqlSaveTimeout, false)
  287. this.onlineProcess(this.reLogin)
  288. //断线重连时不需要重新下发
  289. //if data == nil || data.(bool) {
  290. // this.StartupProto()
  291. //}
  292. //暂时处理成全量下发
  293. this.StartupProto()
  294. //获取创建角色时的奖励
  295. //新注册的系统邮件需求
  296. this.createRoleReward()
  297. this.registerServerList(this.GetRoleBase().RoleData().HeadFrameId, this.GetRoleLevel())
  298. ///////////////////////////////
  299. //通知social,玩家上线
  300. this.playerSocialOnline()
  301. //上线请求公会信息//不一定是重登陆,有可能是顶号
  302. /*//客户端确定会发,不需要做保底
  303. reqMsg := &serverproto.SSOnlineGuildInfoReq{}
  304. reqMsg.Uid = this.GetUUid()
  305. reqMsg.GuildId = this.GetRoleGuildId()
  306. reqMsg.IsRelogin = true
  307. this.SendGuild(reqMsg)
  308. */
  309. if this.reLogin {
  310. this.playerGuildOnline(1)
  311. }
  312. this.reLogin = false
  313. if runeExplore := this.GetRoleRune(); runeExplore != nil {
  314. runeExplore.RuneExploreEndAward()
  315. }
  316. util.InfoF("uuid=%v RoleOnline", this.uuid)
  317. return ROLE_STATE_ONLINE
  318. }
  319. func (this *Role) RoleOffline() int32 {
  320. ////发送logout给客户端
  321. //ntf := &serverproto.SCLogoutNtf{
  322. // Error: int32(serverproto.ErrorCode_ERROR_OK),
  323. //}
  324. //this.ReplayGate(ntf, true)
  325. //log.Println("[RoleOffline]SSUserKickNtf sessionID:",this.CliID().SessID)
  326. if this.GetState() != ROLE_STATE_ONLINE {
  327. return ROLE_STATE_ZOMBIE
  328. }
  329. //通知gate踢人,并且不再反向通知logic服务器
  330. kickNtf := &serverproto.SSUserKickNtf{
  331. Error: int32(serverproto.ErrorCode_ERROR_OK),
  332. ClientId: this.CliID().SessID,
  333. }
  334. this.ReplayGate(kickNtf, false)
  335. this.GetRoleBase().OfflineOnlineTimeProcess()
  336. //设置离线时间
  337. onlineDuration := this.GetRoleBase().SetLastLoginTime()
  338. //更新简介信息中的离线时间
  339. this.GetRoleBase().UpdatePlayerBriefInfo(true)
  340. //this.Save() 主update中会进行离线超时保存操作,避免每次下线都进行数据库保存操作
  341. this.saveTimer.Cancel()
  342. //避免大批量离线操作
  343. this.offlineTimer.Reset(util.GetTimeMilliseconds(), roleOfflineTimeout+time.Duration(rand.Int31n(500)), false)
  344. ///////////////////////////////
  345. model.ElasticPutLogInfo(&model.ElasticLogST{
  346. Uid: this.GetUUid(),
  347. NickName: this.GetNickName(),
  348. OpenId: this.GetOpenId(),
  349. LogType: "RoleOffline",
  350. LogDesc: "RoleOffline",
  351. Param1: int(onlineDuration / 1000), //当前在线时间
  352. })
  353. this.MysqlLogNtf(serverproto.MysqlLogType_LType_Offline, []int32{int32(onlineDuration / 1000)}, 0)
  354. //通知social,玩家下线
  355. this.playerSocialOffline()
  356. //玩家离开世界boss
  357. this.PlayerBattleBossOffline()
  358. //离开aoi地图
  359. //客户端没有发送离开协议,直接断开网络处理(下次重新进入,还是说需要断线重连后也在AOI地图中)
  360. this.playerMapOffline()
  361. //下线公会处理
  362. this.playerGuildOnline(2)
  363. // battle下线处理
  364. this.playerBattleOffline()
  365. //注册到服务器列表(获取最近登录的服务器)
  366. this.registerServerList(this.GetRoleBase().RoleData().HeadFrameId, this.GetRoleLevel())
  367. //netease log
  368. nLog := &NeteaseLogCreateRole{
  369. OnlineTime: int(onlineDuration / 1000),
  370. }
  371. nLog.Log(this)
  372. //log.Println("role offline uid:", this.GetUUid())
  373. return ROLE_STATE_OFFLINE
  374. }
  375. func (this *Role) createRoleReward() {
  376. //获取创建角色时的奖励
  377. //新注册的系统邮件需求
  378. if this.base.roleBase != nil && !this.base.roleBase.CreateReward {
  379. this.base.roleBase.CreateReward = true
  380. this.base.SetDirty(true)
  381. this.GetRoleMail().AddMail(17, serverproto.MailType_MailType_System,
  382. model.GlobalCreateRoleMailReward, nil, "", "")
  383. this.roleBag.AddItemList(model.GlobalCreateItemList, AddItemST{AddFrom: AddFrom_CreateRole, Notify: true})
  384. }
  385. }
  386. func (this *Role) LoginAck(err serverproto.ErrorCode) {
  387. ack := &serverproto.SCLoginAck{
  388. ClientId: this.cliID.SessID,
  389. Error: int32(err),
  390. }
  391. if err == serverproto.ErrorCode_ERROR_OK {
  392. this.ReplayGate(ack, false) //gate需要做特殊处理使用
  393. }
  394. this.ReplayGate(ack, true)
  395. }
  396. func (this *Role) registerServerList(headFrameId, level int32) {
  397. if headFrameId == 0 {
  398. //注册日志,添加到elasticsearch
  399. model.ElasticPutLogInfo(&model.ElasticLogST{
  400. Uid: this.GetUUid(),
  401. NickName: this.GetNickName(),
  402. OpenId: this.GetOpenId(),
  403. LogType: "RoleRegister",
  404. LogDesc: "RoleOnline",
  405. })
  406. }
  407. jobCfgId := this.GetRoleBase().RoleData().HeroData.ConfigId
  408. if headFrameId == 0 {
  409. headFrameId = this.GetRoleBase().RoleData().HeadFrameId
  410. }
  411. zoneId := int32(service.GetServiceConfig().Node.Zone)
  412. if this.GetSelectZone() > 0 {
  413. zoneId = this.GetSelectZone()
  414. }
  415. gender := this.GetRoleBase().GetRoleSex() //1 female 2 male
  416. nickName := this.GetNickName()
  417. //tmpOpenId := model.ConvertPlatform(this.GetOpenId(), this.GetPlatform())
  418. urlPath := "/serverlist/add?openid=" + this.GetOpenId()
  419. uuid := this.GetUUid()
  420. go func() {
  421. defer func() {
  422. //打印奔溃信息
  423. if err := recover(); err != nil {
  424. util.InfoF("onError data=%v \n%s\n", err, string(debug.Stack()))
  425. }
  426. }()
  427. tmpRequest := &rocommon.HTTPRequest{}
  428. tmpRequest.ReqCodecName = "httpform"
  429. tmpRequest.ReqMsg = OpenIdServeNode{
  430. ServerId: zoneId,
  431. HeadFrameId: headFrameId,
  432. Level: level, //默认1级
  433. //RecordTime: uint32(util.GetTimeSeconds()),
  434. JobCfgId: jobCfgId,
  435. Gender: gender,
  436. NickName: nickName,
  437. }
  438. parm := GetHttpNodeParam()
  439. httpNode := baseserver.CreateHttpConnector(parm)
  440. err := httpNode.(rocommon.HTTPConnector).Request("POST", urlPath, tmpRequest)
  441. if err != nil {
  442. util.InfoF("uid=%v http Request err=%v", uuid, err)
  443. }
  444. }()
  445. }
  446. //礼包码获取奖励
  447. func (this *Role) GetGiftReward(giftCode string) {
  448. }