league_member.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. package mapLeague
  2. import (
  3. capp "f1-game/internal/cherry_app"
  4. "f1-game/internal/code"
  5. "f1-game/internal/component/redis"
  6. "f1-game/internal/constant"
  7. "f1-game/internal/data"
  8. "f1-game/internal/enum"
  9. nameActor "f1-game/internal/name/actor"
  10. nameLocal "f1-game/internal/name/local"
  11. nameRedis "f1-game/internal/name/redis"
  12. nameRemote "f1-game/internal/name/remote"
  13. nameRoute "f1-game/internal/name/route"
  14. "f1-game/internal/pb"
  15. "f1-game/internal/sessions"
  16. "f1-game/nodes/map/internal/db"
  17. mapFacade "f1-game/nodes/map/internal/facade"
  18. leagueBase "f1-game/nodes/map/league/base"
  19. leagueMember "f1-game/nodes/map/league/member"
  20. cstring "github.com/cherry-game/cherry/extend/string"
  21. ctime "github.com/cherry-game/cherry/extend/time"
  22. cfacade "github.com/cherry-game/cherry/facade"
  23. cherryLogger "github.com/cherry-game/cherry/logger"
  24. cproto "github.com/cherry-game/cherry/net/proto"
  25. )
  26. func (p *actorLeague) initLeagueMember() {
  27. p.Local().Register(nameLocal.MapLeague_Members, p.leagueMembers)
  28. p.Local().Register(nameLocal.MapLeague_JobInfo, p.leagueJobInfo)
  29. p.Local().Register(nameLocal.MapLeague_JobSet, p.leagueJobSet)
  30. p.Local().Register(nameLocal.MapLeague_JobResigned, p.leagueJobResigned)
  31. p.Local().Register(nameLocal.MapLeague_PermissionSet, p.leaguePermissionSet)
  32. p.Local().Register(nameLocal.MapLeague_Transfer, p.leagueTransfer)
  33. p.Local().Register(nameLocal.MapLeague_TransferCancel, p.leagueTransferCancel)
  34. p.Local().Register(nameLocal.MapLeague_Quit, p.leagueQuit)
  35. p.Local().Register(nameLocal.MapLeague_Kick, p.leagueKick)
  36. p.Local().Register(nameLocal.MapLeague_LeagueImpeachInfo, p.leagueImpeachInfo)
  37. p.Local().Register(nameLocal.MapLeague_LeagueImpeach, p.leagueImpeach)
  38. p.Local().Register(nameLocal.MapLeague_LeagueImpeachVote, p.leagueImpeachVote)
  39. p.Local().Register(nameLocal.MapLeague_MemberRecordInfo, p.leagueMemberRecord)
  40. p.Local().Register(nameLocal.MapLeague_MemberRecordUpdate, p.leagueMemberRecordUpdate)
  41. p.Remote().Register(nameRemote.MapLeague_ManagerList, p.leagueManagerList)
  42. }
  43. // 获取联盟成员列表
  44. func (p *actorLeague) leagueMembers(session *cproto.Session, _ *pb.None) {
  45. playerID := sessions.GetPlayerID(session)
  46. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  47. if !found {
  48. p.ResponseCode(session, code.LeagueMembersEmpty)
  49. return
  50. }
  51. if !leagueMemberTable.CheckMemberExist(playerID) {
  52. p.ResponseCode(session, code.LeagueNotJoin)
  53. return
  54. }
  55. var (
  56. playerIDs = []int64{}
  57. resp = &pb.LeagueMembers{}
  58. )
  59. for playerID, member := range leagueMemberTable.Members {
  60. resp.List = append(resp.List, &pb.LeagueMember{
  61. PlayerID: playerID,
  62. Job: leagueMemberTable.LeagueMember.GetLeagueMemberJob(playerID),
  63. WeeklyFund: member.WeeklyFund,
  64. })
  65. playerIDs = append(playerIDs, playerID)
  66. }
  67. if len(playerIDs) > 0 {
  68. playerDataMap := redis.Game.GetPlayerDataMap(playerIDs, nameRedis.PlayerLeagueMemberFields...)
  69. if playerDataMap != nil {
  70. for _, leagueMember := range resp.List {
  71. playerData, found := playerDataMap[leagueMember.PlayerID]
  72. if found {
  73. leagueMember.PlayerName = playerData.PlayerName
  74. leagueMember.Level = playerData.LordLevel
  75. leagueMember.Point = &pb.Point{X: playerData.X, Y: playerData.Y}
  76. }
  77. }
  78. }
  79. }
  80. // 判断是否存在转让信息
  81. if leagueMemberTable.Transfer.PlayerID > 0 {
  82. resp.Transfer = &pb.LeagueTransfer{
  83. PlayerID: leagueMemberTable.Transfer.PlayerID,
  84. PlayerName: leagueMember.Service().GetPlayerName(leagueMemberTable.Transfer.PlayerID),
  85. TransferEndTime: leagueMemberTable.Transfer.EndTime,
  86. }
  87. }
  88. p.Response(session, resp)
  89. }
  90. // 获取职位信息
  91. func (p *actorLeague) leagueJobInfo(session *cproto.Session, req *pb.None) {
  92. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  93. if !found {
  94. p.ResponseCode(session, code.LeagueMembersEmpty)
  95. return
  96. }
  97. // 获取职位的玩家ID列表
  98. playerList := leagueMemberTable.LeagueMember.GetJobPlayerList()
  99. // 获取玩家基础信息
  100. playerMap := redis.Game.GetPlayerDataMap(playerList, nameRedis.PlayerNameFields...)
  101. list := []*pb.LeagueJobInfo{}
  102. leagueJobs := data.LeagueJob.List()
  103. for _, leagueJobRow := range leagueJobs {
  104. var (
  105. jobID = leagueJobRow.JobID
  106. playerName = ""
  107. playerID, found = leagueMemberTable.LeagueJob.Jobs[jobID]
  108. permissions, pFound = leagueMemberTable.LeagueJob.Permissions[jobID]
  109. )
  110. // 没有职位且职位没有权限
  111. if !found && !pFound {
  112. continue
  113. }
  114. if playerID > 0 {
  115. playerData, found := playerMap[playerID]
  116. if found {
  117. playerName = playerData.PlayerName
  118. }
  119. }
  120. list = append(list, &pb.LeagueJobInfo{
  121. JobID: jobID,
  122. PlayerID: playerID,
  123. PlayerName: playerName,
  124. Permissions: permissions,
  125. })
  126. }
  127. resp := &pb.LeagueJobList{
  128. List: list,
  129. }
  130. p.Response(session, resp)
  131. }
  132. // 联盟职位设置
  133. func (p *actorLeague) leagueJobSet(session *cproto.Session, req *pb.I64I32) {
  134. var (
  135. targetPlayerID = req.Key
  136. jobID = req.Value
  137. )
  138. if targetPlayerID <= 0 || jobID <= 0 {
  139. p.ResponseCode(session, code.RequestParamsError)
  140. return
  141. }
  142. leagueTable, found := db.GetMapLeagueTable(p.leagueID)
  143. if !found {
  144. p.ResponseCode(session, code.LeagueNotExist)
  145. return
  146. }
  147. opPlayerID := sessions.GetPlayerID(session)
  148. // 只有盟主有权限设置权限
  149. if !leagueTable.LeagueInfo.IsLeader(opPlayerID) {
  150. p.ResponseCode(session, code.LeaguePermissionDenied)
  151. return
  152. }
  153. if opPlayerID == targetPlayerID {
  154. p.ResponseCode(session, code.LeagueNoCanSetSelfJob)
  155. return
  156. }
  157. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  158. if !found {
  159. p.ResponseCode(session, code.LeagueMembersEmpty)
  160. return
  161. }
  162. // 判断玩家是否在联盟内
  163. if found = leagueMemberTable.LeagueMember.CheckMemberExist(targetPlayerID); !found {
  164. p.ResponseCode(session, code.LeagueMemberNotExist)
  165. return
  166. }
  167. // 判断职位是否存在
  168. leagueJobRow, found := data.LeagueJob.GetByJobID(jobID)
  169. if !found {
  170. p.ResponseCode(session, code.LeagueJobNotExist)
  171. return
  172. }
  173. // 不能设置为盟主
  174. if leagueJobRow.JobType == enum.JobType_Leader {
  175. p.ResponseCode(session, code.LeagueLeaderNotCanSet)
  176. return
  177. }
  178. // 更新的玩家列表
  179. var changePlayerID = []int64{
  180. targetPlayerID,
  181. }
  182. // 先卸任玩家之前的职位
  183. leagueMemberTable.Resigned(targetPlayerID)
  184. // 设置新职位, 返回被卸任的玩家ID
  185. jobOldPlayerID := leagueMemberTable.SetLeagueMemberJob(jobID, targetPlayerID)
  186. leagueMemberTable.Save2Queue()
  187. if jobOldPlayerID > 0 {
  188. changePlayerID = append(changePlayerID, jobOldPlayerID)
  189. }
  190. // TODO 如果有其他人更新职位加在后面
  191. updateLeagueInfo2Redis(leagueTable, leagueMemberTable, changePlayerID...)
  192. // 通知玩家职位变更
  193. p.PermissionChangePush(leagueMemberTable, changePlayerID...)
  194. resp := &pb.I64I32{
  195. Key: targetPlayerID,
  196. Value: jobID,
  197. }
  198. p.Response(session, resp)
  199. }
  200. // 联盟卸任职位
  201. func (p *actorLeague) leagueJobResigned(session *cproto.Session, req *pb.I64) {
  202. var (
  203. targetPlayerID = req.Value
  204. opPlayerID = sessions.GetPlayerID(session)
  205. )
  206. if targetPlayerID <= 0 {
  207. p.ResponseCode(session, code.RequestParamsError)
  208. return
  209. }
  210. leagueTable, found := db.GetMapLeagueTable(p.leagueID)
  211. if !found {
  212. p.ResponseCode(session, code.LeagueNotExist)
  213. return
  214. }
  215. // 只有盟主有权限设置权限
  216. if !leagueTable.LeagueInfo.IsLeader(opPlayerID) {
  217. p.ResponseCode(session, code.LeaguePermissionDenied)
  218. return
  219. }
  220. // 不能卸任自己的职位
  221. if opPlayerID == targetPlayerID {
  222. p.ResponseCode(session, code.LeagueNotCanOpSelf)
  223. return
  224. }
  225. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  226. if !found {
  227. p.ResponseCode(session, code.LeagueMembersEmpty)
  228. return
  229. }
  230. list := leagueMemberTable.Resigned(targetPlayerID)
  231. // 卸任职位
  232. if len(list) > 0 {
  233. leagueMemberTable.Save2Queue()
  234. }
  235. var (
  236. jobID = cstring.ToString(list[0])
  237. leagueLogTable, _ = db.GetMapLeagueLogTable(p.leagueID)
  238. playerName = leagueMember.Service().GetPlayerName(targetPlayerID)
  239. )
  240. // 写入日志
  241. leagueLogTable.AddLeagueLog(enum.Log_LeagueJobRegined, playerName, jobID)
  242. // 通知玩家职位变更
  243. p.PermissionChangePush(leagueMemberTable, targetPlayerID)
  244. resp := &pb.I64{
  245. Value: targetPlayerID,
  246. }
  247. p.Response(session, resp)
  248. }
  249. // 盟主转让
  250. func (p *actorLeague) leagueTransfer(session *cproto.Session, req *pb.I64) {
  251. var (
  252. targetPlayerID = req.Value
  253. opPlayerID = sessions.GetPlayerID(session)
  254. )
  255. if targetPlayerID <= 0 {
  256. p.ResponseCode(session, code.RequestParamsError)
  257. return
  258. }
  259. leagueTable, found := db.GetMapLeagueTable(p.leagueID)
  260. if !found {
  261. p.ResponseCode(session, code.LeagueNotExist)
  262. return
  263. }
  264. // 不是盟主
  265. if ok := leagueTable.LeagueInfo.IsLeader(opPlayerID); !ok {
  266. p.ResponseCode(session, code.LeagueNotLeader)
  267. return
  268. }
  269. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  270. if !found {
  271. p.ResponseCode(session, code.LeagueMembersEmpty)
  272. return
  273. }
  274. // 转让玩家不是联盟成员
  275. if found = leagueMemberTable.LeagueMember.CheckMemberExist(targetPlayerID); !found {
  276. p.ResponseCode(session, code.LeagueTransferNotMember)
  277. return
  278. }
  279. // 判断当前是否存在转让数据
  280. if leagueMemberTable.LeagueMember.Transfer.PlayerID > 0 {
  281. p.ResponseCode(session, code.LeagueTransferExist)
  282. return
  283. }
  284. // 盟主正在被弹劾 无法转让
  285. if leagueMemberTable.Impeach.PlayerID > 0 {
  286. p.ResponseCode(session, code.LeagueImpeachNotTransfer)
  287. return
  288. }
  289. // 设置转让数据
  290. endTime := ctime.Now().ToSecond() + data.Const.LeagueTransferTime
  291. leagueMemberTable.SetLeagueTransfer(targetPlayerID, endTime)
  292. leagueMemberTable.Save2Queue()
  293. resp := &pb.LeagueTransfer{
  294. PlayerID: targetPlayerID,
  295. PlayerName: leagueMember.Service().GetPlayerName(targetPlayerID),
  296. TransferEndTime: endTime,
  297. }
  298. p.Response(session, resp)
  299. }
  300. // 盟主转让取消
  301. func (p *actorLeague) leagueTransferCancel(session *cproto.Session, _ *pb.None) {
  302. var (
  303. opPlayerID = sessions.GetPlayerID(session)
  304. )
  305. leagueTable, found := db.GetMapLeagueTable(p.leagueID)
  306. if !found {
  307. p.ResponseCode(session, code.LeagueNotExist)
  308. return
  309. }
  310. // 不是盟主
  311. if ok := leagueTable.LeagueInfo.IsLeader(opPlayerID); !ok {
  312. p.ResponseCode(session, code.LeagueNotLeader)
  313. return
  314. }
  315. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  316. if !found {
  317. p.ResponseCode(session, code.LeagueMembersEmpty)
  318. return
  319. }
  320. if leagueMemberTable.LeagueMember.Transfer.PlayerID <= 0 {
  321. p.ResponseCode(session, code.LeagueTransferNotExist)
  322. return
  323. }
  324. // 取消转让
  325. leagueMemberTable.SetLeagueTransfer(0, 0)
  326. leagueMemberTable.Save2Queue()
  327. p.ResponseCode(session, code.OK)
  328. }
  329. // 获取盟主弹劾信息
  330. func (p *actorLeague) leagueImpeachInfo(session *cproto.Session, _ *pb.None) {
  331. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  332. if !found {
  333. p.ResponseCode(session, code.LeagueMembersEmpty)
  334. return
  335. }
  336. resp := leagueMemberTable.LeagueMember.ToLeagueImpeachProto()
  337. p.Response(session, resp)
  338. }
  339. // 弹劾盟主
  340. func (p *actorLeague) leagueImpeach(session *cproto.Session, _ *pb.None) {
  341. var (
  342. leagueID = p.leagueID
  343. playerID = sessions.GetPlayerID(session)
  344. )
  345. leagueTable, found := db.GetMapLeagueTable(leagueID)
  346. if !found {
  347. p.ResponseCode(session, code.LeagueNotExist)
  348. return
  349. }
  350. // 盟主不能弹劾自己
  351. if ok := leagueTable.LeagueInfo.IsLeader(playerID); ok {
  352. p.ResponseCode(session, code.LeagueImpeachSelf)
  353. return
  354. }
  355. leagueMemberTable, found := db.GetMapLeagueMemberTable(leagueID)
  356. if found {
  357. p.ResponseCode(session, code.LeagueMembersEmpty)
  358. return
  359. }
  360. // 检测玩家是否是同盟成员
  361. if found = leagueMemberTable.LeagueMember.CheckMemberExist(playerID); !found {
  362. p.ResponseCode(session, code.LeagueMemberNotExist)
  363. return
  364. }
  365. // TODO 判断当前赛季阶段是否可以执行弹劾 需要判断结束时间是否会超出弹劾的阶段时间
  366. // 检测是否存在其他弹劾数据
  367. if ok := leagueMemberTable.LeagueMember.CheckLeagueImpeachExist(); ok {
  368. p.ResponseCode(session, code.LeagueImpeachNotEnd)
  369. return
  370. }
  371. nowSecond := ctime.Now().ToSecond()
  372. // 判断玩家是否符合条件
  373. if ok := p.CheckLeagueMemberCanImpeach(leagueMemberTable, playerID, nowSecond); !ok {
  374. p.ResponseCode(session, code.LeagueImpeachNotEnough)
  375. return
  376. }
  377. // 取消当前盟主转让 推送给盟主
  378. leagueMemberTable.SetLeagueTransfer(0, 0)
  379. // 获取能发起弹劾投票的玩家数量
  380. voteCount := p.getLeagueImpeachVoteCount(leagueTable.LeagueInfo.LeaderID, leagueMemberTable, nowSecond)
  381. // 开始执行弹劾
  382. leagueMemberTable.HandleLeagueImpeach(playerID, voteCount, nowSecond)
  383. // TODO 盟主和可执行弹劾成员发送邮件
  384. resp := leagueMemberTable.LeagueMember.ToLeagueImpeachProto()
  385. p.Response(session, resp)
  386. }
  387. // 联盟弹劾投票
  388. func (p *actorLeague) leagueImpeachVote(session *cproto.Session, req *pb.Bool) {
  389. var (
  390. leagueID = p.leagueID
  391. playerID = sessions.GetPlayerID(session)
  392. agree = req.Value
  393. )
  394. leagueTable, found := db.GetMapLeagueTable(leagueID)
  395. if !found {
  396. p.ResponseCode(session, code.LeagueNotExist)
  397. return
  398. }
  399. // 盟主不能投票
  400. if leagueTable.LeagueInfo.IsLeader(playerID) {
  401. p.ResponseCode(session, code.LeagueImpeachSelf)
  402. return
  403. }
  404. leagueMemberTable, found := db.GetMapLeagueMemberTable(leagueID)
  405. if found {
  406. p.ResponseCode(session, code.LeagueMembersEmpty)
  407. return
  408. }
  409. // 检测玩家是否是同盟成员
  410. if found = leagueMemberTable.LeagueMember.CheckMemberExist(playerID); !found {
  411. p.ResponseCode(session, code.LeagueMemberNotExist)
  412. return
  413. }
  414. // 检测是否存在其他弹劾信息
  415. if ok := leagueMemberTable.LeagueMember.CheckLeagueImpeachExist(); ok {
  416. p.ResponseCode(session, code.LeagueImpeachNotEnd)
  417. return
  418. }
  419. impeachTime := leagueMemberTable.Impeach.ImpeachTime
  420. // 判断玩家是否符合条件
  421. if ok := p.CheckLeagueMemberCanImpeach(leagueMemberTable, playerID, impeachTime); !ok {
  422. p.ResponseCode(session, code.LeagueImpeachNotEnough)
  423. return
  424. }
  425. // 进行投票
  426. leagueMemberTable.LeagueMember.LeagueImpeachVote(playerID, agree)
  427. // 判断是否提前结束
  428. p.CheckLeagueImpeachEnd(leagueMemberTable)
  429. resp := leagueMemberTable.LeagueMember.ToLeagueImpeachProto()
  430. p.Response(session, resp)
  431. }
  432. // 权限设置
  433. func (p *actorLeague) leaguePermissionSet(session *cproto.Session, req *pb.LeaguePermissionRequest) {
  434. var (
  435. opPlayerID = sessions.GetPlayerID(session)
  436. jobs = req.Jobs
  437. )
  438. if len(jobs) <= 0 {
  439. p.ResponseCode(session, code.RequestParamsError)
  440. return
  441. }
  442. leagueTable, found := db.GetMapLeagueTable(p.leagueID)
  443. if !found {
  444. p.ResponseCode(session, code.LeagueNotExist)
  445. return
  446. }
  447. // 只有盟主能设置权限
  448. if !leagueTable.LeagueInfo.IsLeader(opPlayerID) {
  449. p.ResponseCode(session, code.LeaguePermissionDenied)
  450. return
  451. }
  452. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  453. if !found {
  454. p.ResponseCode(session, code.LeagueMembersEmpty)
  455. return
  456. }
  457. // 检测设置权限是否合法
  458. for _, job := range jobs {
  459. var (
  460. jobID = job.Job
  461. permissions = job.Permissions
  462. )
  463. leagueJobRow, found := data.LeagueJob.GetByJobID(jobID)
  464. if !found {
  465. p.ResponseCode(session, code.LeagueJobNotExist)
  466. return
  467. }
  468. for _, permID := range permissions {
  469. // 权限不存在
  470. if !enum.CheckLeaguePermissionExist(permID) {
  471. p.ResponseCode(session, code.LeaguePermissionNotExist)
  472. return
  473. }
  474. // 当前权限不能设置
  475. if found := leagueJobRow.JobNotSetPerm.Contains(permID); found {
  476. cherryLogger.Warnf("[leagueID=%d] permission not can set. job:%d, permID:%d", p.leagueID, jobID, permID)
  477. p.ResponseCode(session, code.LeaguePermissionNoCanSet)
  478. return
  479. }
  480. }
  481. }
  482. updatePlayerIDs := []int64{}
  483. // 设置权限
  484. for _, job := range jobs {
  485. playerID := leagueMemberTable.GetJobPlayerID(job.Job)
  486. if playerID > 0 {
  487. updatePlayerIDs = append(updatePlayerIDs, playerID)
  488. }
  489. leagueMemberTable.SetLeagueJobPermission(job.Job, job.Permissions)
  490. }
  491. leagueMemberTable.Save2Queue()
  492. // 通知玩家权限变更
  493. p.PermissionChangePush(leagueMemberTable, updatePlayerIDs...)
  494. p.ResponseCode(session, code.OK)
  495. }
  496. // 退出联盟
  497. func (p *actorLeague) leagueQuit(session *cproto.Session, req *pb.None) {
  498. playerID := sessions.GetPlayerID(session)
  499. if playerID < 1 {
  500. p.ResponseCode(session, code.PlayerIDError)
  501. return
  502. }
  503. leagueTable, found := db.GetMapLeagueTable(p.leagueID)
  504. if !found {
  505. p.ResponseCode(session, code.LeagueNotExist)
  506. return
  507. }
  508. // 判断targetPlayerID是否为会长
  509. if leagueTable.LeagueInfo.IsLeader(playerID) {
  510. p.ResponseCode(session, code.LeagueLeaderNotQuit)
  511. return
  512. }
  513. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  514. if !found {
  515. p.ResponseCode(session, code.LeagueMembersEmpty)
  516. return
  517. }
  518. quitReq := &pb.I64{
  519. Value: p.leagueID,
  520. }
  521. // 通知map_player 玩家退出联盟
  522. targetPath := cfacade.NewChildPath(capp.NodeID(), nameActor.Map_Player, playerID)
  523. errCode := capp.Call(targetPath, nameRemote.MapLeague_QuitNotice, quitReq)
  524. if code.IsFail(errCode) {
  525. p.ResponseCode(session, errCode)
  526. return
  527. }
  528. // 玩家退出联盟
  529. p.doLeagueMemberQuit(leagueTable, leagueMemberTable, playerID, true)
  530. // 更新redis
  531. leagueQuitUpdateRedis(playerID)
  532. // 写入日志
  533. p.addLeagueLog(enum.Log_LeagueQuit, playerID)
  534. p.ResponseCode(session, code.OK)
  535. }
  536. // 退出联盟更新redis
  537. func leagueQuitUpdateRedis(playerID int64) {
  538. fields := map[string]any{}
  539. fields[nameRedis.Player_LeagueID] = 0
  540. fields[nameRedis.Player_LeagueName] = ""
  541. fields[nameRedis.Player_LeagueJob] = 0
  542. redis.Game.SavePlayerDataFields(playerID, fields)
  543. }
  544. // 踢出联盟
  545. func (p *actorLeague) leagueKick(session *cproto.Session, req *pb.I64) {
  546. var (
  547. opPlayerID = sessions.GetPlayerID(session)
  548. targetPlayerID = req.Value
  549. )
  550. if targetPlayerID <= 0 {
  551. p.ResponseCode(session, code.IllegalArgument)
  552. return
  553. }
  554. if opPlayerID == targetPlayerID {
  555. p.ResponseCode(session, code.LeagueNotCanOpSelf)
  556. return
  557. }
  558. leagueTable, found := db.GetMapLeagueTable(p.leagueID)
  559. if !found {
  560. p.ResponseCode(session, code.LeagueNotExist)
  561. return
  562. }
  563. // 判断targetPlayerID是否为盟主
  564. if leagueTable.LeagueInfo.IsLeader(targetPlayerID) {
  565. p.ResponseCode(session, code.LeagueLeaderNotQuit)
  566. return
  567. }
  568. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  569. if !found {
  570. p.ResponseCode(session, code.LeagueMembersEmpty)
  571. return
  572. }
  573. // 判断踢出成员是否存在
  574. if ok := leagueMemberTable.LeagueMember.CheckMemberExist(targetPlayerID); !ok {
  575. p.ResponseCode(session, code.LeagueMemberNotExist)
  576. return
  577. }
  578. // targetPlayerID 被踢出 判断opPlayerID是否有权限
  579. if !leagueMemberTable.LeagueMember.CheckPermission(opPlayerID, enum.League_Permission_Member) {
  580. p.ResponseCode(session, code.LeaguePermissionDenied)
  581. return
  582. }
  583. // 弹劾中不能被踢出
  584. if leagueMemberTable.IsImpeachPlayer(targetPlayerID) {
  585. p.ResponseCode(session, code.LeagueImpeachNotKick)
  586. return
  587. }
  588. quitReq := &pb.I64{
  589. Value: p.leagueID,
  590. }
  591. // 通知map_player 玩家退出联盟
  592. targetPath := cfacade.NewChildPath(capp.NodeID(), nameActor.Map_Player, targetPlayerID)
  593. errCode := capp.Call(targetPath, nameRemote.MapLeague_QuitNotice, quitReq)
  594. if code.IsFail(errCode) {
  595. p.ResponseCode(session, errCode)
  596. return
  597. }
  598. // 踢出targetPlayerID
  599. p.doLeagueMemberQuit(leagueTable, leagueMemberTable, targetPlayerID, false)
  600. // 更新redis
  601. leagueQuitUpdateRedis(targetPlayerID)
  602. var (
  603. leagueLogTable, _ = db.GetMapLeagueLogTable(p.leagueID)
  604. opJobId = cstring.ToString(leagueMemberTable.LeagueMember.GetLeagueMemberJob(opPlayerID))
  605. opPlayerName = leagueMember.Service().GetPlayerName(opPlayerID)
  606. targetPlayerName = leagueMember.Service().GetPlayerName(targetPlayerID)
  607. )
  608. // 写入日志
  609. leagueLogTable.AddLeagueLog(enum.Log_LeagueKick, opJobId, opPlayerName, targetPlayerName)
  610. p.ResponseCode(session, code.OK)
  611. }
  612. // 执行加入联盟
  613. func (p *actorLeague) doLeagueMemberJoin(leagueTable *db.MapLeagueTable, leagueMemberTable *db.MapLeagueMemberTable, joinPlayerIDs ...int64) {
  614. if len(joinPlayerIDs) <= 0 {
  615. return
  616. }
  617. for _, joinPlayerID := range joinPlayerIDs {
  618. // 更新联盟成员列表
  619. leagueMemberTable.LeagueMember.LeagueJoin(joinPlayerID)
  620. // 写入日志
  621. p.addLeagueLog(enum.Log_LeagueJoin, joinPlayerID)
  622. session, found := sessions.GetSession(joinPlayerID)
  623. if !found {
  624. continue
  625. }
  626. // 推送通知
  627. mapFacade.LeagueServicePush(p.leagueTable, session)
  628. }
  629. // 更新联盟信息中的成员数量
  630. leagueTable.LeagueInfo.MemberCount = leagueMemberTable.GetLeagueMemberCount()
  631. leagueMemberTable.Save2Queue()
  632. // 更新玩家联盟信息
  633. updateLeagueInfo2Redis(leagueTable, leagueMemberTable, joinPlayerIDs...)
  634. leagueBase.Service().SyncLeaguePrestigeRank(p.leagueTable, leagueMemberTable)
  635. }
  636. // 执行退出/踢出联盟
  637. func (p *actorLeague) doLeagueMemberQuit(leagueTable *db.MapLeagueTable, leagueMemberTable *db.MapLeagueMemberTable, targetPlayerID int64, quit bool) {
  638. // 成员退出/踢出
  639. if ok := leagueMemberTable.MemberQuitOrKick(targetPlayerID, quit); !ok {
  640. return
  641. }
  642. // 如果存在转让数据 清除
  643. if leagueMemberTable.Transfer.PlayerID == targetPlayerID {
  644. leagueMemberTable.SetLeagueTransfer(0, 0)
  645. }
  646. // 更新联盟当前人数
  647. leagueTable.LeagueInfo.MemberCount = leagueMemberTable.GetLeagueMemberCount()
  648. // 删除玩家入驻信息 如果存在 并通知所有成员
  649. if ok := leagueTable.RemoveResidence(targetPlayerID); ok {
  650. p.LeagueResidenceRemoveNotice(leagueMemberTable.GetLeagueMemberIDs(), targetPlayerID)
  651. }
  652. leagueTable.Save2Queue()
  653. leagueMemberTable.Save2Queue()
  654. // 同步联盟声望
  655. leagueBase.Service().SyncLeaguePrestigeRank(p.leagueTable, leagueMemberTable)
  656. }
  657. func (p *actorLeague) addLeagueLog(logID int32, playerID int64) {
  658. // 写入加入日志
  659. var (
  660. leagueLogTable, _ = db.GetMapLeagueLogTable(p.leagueID)
  661. playerName = leagueMember.Service().GetPlayerName(playerID)
  662. )
  663. leagueLogTable.AddLeagueLog(logID, playerName)
  664. }
  665. // 检测弹劾是否结束
  666. func (p *actorLeague) CheckLeagueImpeachEnd(leagueMemberTable *db.MapLeagueMemberTable) {
  667. var (
  668. agreeCount = int32(len(leagueMemberTable.Impeach.AgreePlayerIDs))
  669. rejectCount = int32(len(leagueMemberTable.Impeach.RejectPlayerIDs))
  670. newLeaderID = leagueMemberTable.Impeach.PlayerID
  671. needCount = leagueMemberTable.Impeach.Total / 2
  672. isEnd = false
  673. )
  674. // 弹劾成功
  675. if rejectCount < agreeCount && agreeCount > needCount {
  676. // 盟主转换
  677. leagueTable, found := db.GetMapLeagueTable(p.leagueID)
  678. if !found {
  679. cherryLogger.Warnf("league impeach finish fail, league not found. leagueID:%d", p.leagueID)
  680. return
  681. }
  682. oldLeaderID := leagueTable.LeagueInfo.LeaderID
  683. leagueTable.LeagueInfo.LeaderID = newLeaderID
  684. // 如果弹劾玩家存在职位 需要先卸载职位
  685. jobIDs := leagueMemberTable.Resigned(newLeaderID)
  686. // 设置职位
  687. if len(jobIDs) > 0 {
  688. leagueMemberTable.SetLeagueMemberJob(jobIDs[0], newLeaderID)
  689. }
  690. leagueTable.Save2Queue()
  691. // 通知玩家职位变更
  692. p.PermissionChangePush(leagueMemberTable, oldLeaderID, newLeaderID)
  693. // 更新redis
  694. updateLeagueInfo2Redis(leagueTable, leagueMemberTable, oldLeaderID, newLeaderID)
  695. isEnd = true
  696. }
  697. // 弹劾失败
  698. if agreeCount < rejectCount && rejectCount > needCount/2 {
  699. isEnd = true
  700. }
  701. if isEnd {
  702. leagueMemberTable.LeagueImpeachClear(newLeaderID)
  703. leagueMemberTable.Save2Queue()
  704. }
  705. }
  706. // 判断联盟成员是否可以进行弹劾
  707. func (p *actorLeague) CheckLeagueMemberCanImpeach(leagueMemeberTable *db.MapLeagueMemberTable, playerID int64, impeachTime int64) bool {
  708. leagueMember, found := leagueMemeberTable.LeagueMember.GetLeagueMember(playerID)
  709. if !found {
  710. return false
  711. }
  712. // 弹劾投票所需入盟时间
  713. needTime := data.Const.LeagueImpeachMemberTime * ctime.SecondsPerHour
  714. // 玩家加入联盟时间超出x小时
  715. if impeachTime-leagueMember.JoinTime < needTime {
  716. return false
  717. }
  718. // TODO 玩家个人声望大于xxx
  719. return true
  720. }
  721. func (p *actorLeague) getLeagueImpeachVoteCount(leaderID int64, leagueMemberTable *db.MapLeagueMemberTable, impeachTime int64) int32 {
  722. total := int32(0)
  723. // 弹劾投票所需入盟时间
  724. var (
  725. needTime = data.Const.LeagueImpeachMemberTime * ctime.SecondsPerHour
  726. // TODO 后续接入声望开启
  727. //needPrestige = data.Const.LeagueImpeachMemberPrestige
  728. playerIDs = []int64{}
  729. )
  730. for playerID, member := range leagueMemberTable.Members {
  731. // 排除盟主
  732. if leaderID != playerID && impeachTime-member.JoinTime >= needTime {
  733. playerIDs = append(playerIDs, playerID)
  734. }
  735. }
  736. if len(playerIDs) > 0 {
  737. playerDataMap := redis.Game.GetPlayerDataMap(playerIDs, nameRedis.PlayerBaseFields...)
  738. for _, playerID := range playerIDs {
  739. playerData, found := playerDataMap[playerID]
  740. // TODO redis获取玩家声望 判断玩家声望是否满足 现在暂时使用等级判断
  741. if found && playerData.LordLevel >= 0 {
  742. total++
  743. }
  744. }
  745. }
  746. return total
  747. }
  748. func (p *actorLeague) JobPush(playerID int64) {
  749. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  750. if !found {
  751. return
  752. }
  753. jobID := leagueMemberTable.LeagueMember.GetLeagueMemberJob(playerID)
  754. // 没有职位
  755. if jobID <= 0 {
  756. return
  757. }
  758. session, found := sessions.GetSession(playerID)
  759. if !found {
  760. p.Warn("push player job fail, Session not found. playerID:%d", playerID)
  761. return
  762. }
  763. permissions, _ := leagueMemberTable.GetJobPermissions(jobID)
  764. resp := &pb.LeagueJob{
  765. Job: jobID,
  766. Permissions: permissions,
  767. }
  768. sessions.PushWithSession(session, nameRoute.PushLeague_JobInfo, resp)
  769. }
  770. func (p *actorLeague) PermissionChangePush(leagueMemberTable *db.MapLeagueMemberTable, playerIDs ...int64) {
  771. if len(playerIDs) <= 0 {
  772. return
  773. }
  774. for _, playerID := range playerIDs {
  775. session, found := sessions.GetSession(playerID)
  776. if !found {
  777. continue
  778. }
  779. resp := &pb.LeagueJob{
  780. Job: leagueMemberTable.GetLeagueMemberJob(playerID),
  781. }
  782. // 获取职位权限列表
  783. if resp.Job > 0 {
  784. permissions, _ := leagueMemberTable.GetJobPermissions(resp.Job)
  785. resp.Permissions = permissions
  786. }
  787. sessions.PushWithSession(session, nameRoute.PushLeague_JobChange, resp)
  788. }
  789. }
  790. // 获取联盟成员战绩信息
  791. func (p *actorLeague) leagueMemberRecord(session *cproto.Session, req *pb.I64) {
  792. targetPlayerID := req.Value
  793. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  794. if !found {
  795. p.ResponseCode(session, code.LeagueMembersEmpty)
  796. return
  797. }
  798. leagueMember, found := leagueMemberTable.GetLeagueMember(targetPlayerID)
  799. if !found {
  800. p.ResponseCode(session, code.LeagueMemberNotExist)
  801. return
  802. }
  803. resp := &pb.LeagueMemberRecordInfo{
  804. PlayerID: targetPlayerID,
  805. }
  806. playerData := redis.Game.GetPlayerData(targetPlayerID, nameRedis.PlayerBaseFields...)
  807. if playerData != nil {
  808. resp.PlayerName = playerData.PlayerName
  809. resp.LordLevel = playerData.LordLevel
  810. resp.IconID = playerData.IconID
  811. resp.FrameID = playerData.FrameID
  812. resp.Job = leagueMemberTable.GetLeagueMemberJob(targetPlayerID)
  813. }
  814. curWeek := leagueMember.GetLeagueMemberRecordWeek()
  815. for week, record := range leagueMember.RecordMap {
  816. diff := curWeek - week
  817. if diff < 0 {
  818. diff = -diff
  819. }
  820. // 过期周跳过
  821. if diff >= constant.LeagueMamberRecordWeekLimit {
  822. continue
  823. }
  824. resp.Records[diff] = record.ToMemberRecordProto()
  825. }
  826. p.Response(session, resp)
  827. }
  828. // 更新联盟成员战绩
  829. func (p *actorLeague) leagueMemberRecordUpdate(req *pb.LeagueMemberRecordUpdateList) {
  830. list := req.List
  831. if len(list) <= 0 {
  832. return
  833. }
  834. leagueMemberTable, found := db.GetMapLeagueMemberTable(p.leagueID)
  835. if !found {
  836. return
  837. }
  838. for _, playerRecord := range list {
  839. var (
  840. playerID = playerRecord.PlayerID
  841. records = playerRecord.Records
  842. )
  843. leagueMember, found := leagueMemberTable.GetLeagueMember(playerID)
  844. if !found {
  845. continue
  846. }
  847. leagueMember.UpdateMemberRecords(records)
  848. }
  849. }
  850. // 获取联盟管理列表
  851. func (p *actorLeague) leagueManagerList(req *pb.I64) (*pb.LeagueMembers, int32) {
  852. var (
  853. leagueID = req.Value
  854. playerIDs = []int64{}
  855. resp = &pb.LeagueMembers{
  856. List: []*pb.LeagueMember{},
  857. }
  858. )
  859. _, found := db.GetMapLeagueTable(leagueID)
  860. if !found {
  861. return nil, code.LeagueNotExist
  862. }
  863. leagueMemberTable, found := db.GetMapLeagueMemberTable(leagueID)
  864. if !found {
  865. return nil, code.LeagueMembersEmpty
  866. }
  867. jobs := leagueMemberTable.LeagueJob.Jobs
  868. for jobID, playerID := range jobs {
  869. leagueMember := &pb.LeagueMember{
  870. Job: jobID,
  871. PlayerID: playerID,
  872. }
  873. playerIDs = append(playerIDs, playerID)
  874. resp.List = append(resp.List, leagueMember)
  875. }
  876. if len(playerIDs) > 0 {
  877. playerDataMap := redis.Game.GetPlayerDataMap(playerIDs, nameRedis.PlayerBaseFields...)
  878. if playerDataMap != nil {
  879. for _, leagueMember := range resp.List {
  880. playerData, found := playerDataMap[leagueMember.PlayerID]
  881. if found {
  882. leagueMember.PlayerName = playerData.PlayerName
  883. }
  884. }
  885. }
  886. }
  887. return resp, code.OK
  888. }