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