actor.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. package mapLeague
  2. import (
  3. "f1-game/internal/code"
  4. "f1-game/internal/component/redis"
  5. "f1-game/internal/data"
  6. "f1-game/internal/enum"
  7. "f1-game/internal/event"
  8. nameActor "f1-game/internal/name/actor"
  9. nameRedis "f1-game/internal/name/redis"
  10. nameRemote "f1-game/internal/name/remote"
  11. "f1-game/internal/pb"
  12. "f1-game/internal/sessions"
  13. "f1-game/nodes/map/internal/db"
  14. mapFacade "f1-game/nodes/map/internal/facade"
  15. leagueBase "f1-game/nodes/map/league/base"
  16. "strings"
  17. "unicode"
  18. cstring "github.com/cherry-game/cherry/extend/string"
  19. cutils "github.com/cherry-game/cherry/extend/utils"
  20. cfacade "github.com/cherry-game/cherry/facade"
  21. clog "github.com/cherry-game/cherry/logger"
  22. cactor "github.com/cherry-game/cherry/net/actor"
  23. )
  24. type (
  25. actor struct {
  26. cactor.Base
  27. leagueIDs []int64
  28. }
  29. )
  30. func Init(app cfacade.IApplication, leagueTables map[int64]*db.MapLeagueTable) {
  31. actor := NewActor()
  32. app.ActorSystem().CreateActor(actor.AliasID(), actor)
  33. for leagueID := range leagueTables {
  34. actor.leagueIDs = append(actor.leagueIDs, leagueID)
  35. }
  36. }
  37. func NewActor() *actor {
  38. return &actor{}
  39. }
  40. func (p *actor) AliasID() string {
  41. return nameActor.Map_League
  42. }
  43. func (p *actor) OnInit() {
  44. p.Remote().Register(nameRemote.MapLeague_List, p.leagueList)
  45. p.Remote().Register(nameRemote.MapLeague_Search, p.leagueSearch)
  46. p.Remote().Register(nameRemote.MapLeague_Create, p.leagueCreate)
  47. p.Remote().Register(nameRemote.MapLeague_DiplomacyInfos, p.diplomacyInfos)
  48. p.Remote().Register(nameRemote.MapLeague_NameChange, p.leagueNameChange)
  49. p.Remote().Register(nameRemote.MapLeague_AbbNameChange, p.leagueAbbNameChange)
  50. }
  51. func (p *actor) OnLocalReceived(m *cfacade.Message) (bool, bool) {
  52. leagueID := m.Session.GetString(sessions.LeagueID)
  53. if cstring.IsBlank(leagueID) {
  54. clog.Warnf("[OnLocalReceived] league not found. m = %+v", m)
  55. return false, false
  56. }
  57. if child, found := p.Child().Get(leagueID); found {
  58. child.PostLocal(m)
  59. }
  60. return false, false
  61. }
  62. func (p *actor) OnRemoteReceived(m *cfacade.Message) (bool, bool) {
  63. if m.TargetPath().IsParent() {
  64. // 不拦截父actor的remote消息
  65. return true, false
  66. }
  67. childID := m.TargetPath().ChildID
  68. leagueID, ok := cstring.ToInt64(childID)
  69. if !ok {
  70. return false, false
  71. }
  72. if _, found := db.GetMapLeagueTable(leagueID); !found {
  73. clog.Warnf("league table not found. [leagueID = %d, target = %s]", leagueID, m.Target)
  74. return false, false
  75. }
  76. return true, false
  77. }
  78. func (p *actor) OnFindChild(m *cfacade.Message) (cfacade.IActor, bool) {
  79. childID := m.TargetPath().ChildID
  80. leagueID, ok := cstring.ToInt64(childID)
  81. if !ok {
  82. return nil, false
  83. }
  84. childLeague := newActorLeague(leagueID)
  85. childActor, err := p.Child().Create(childID, &childLeague)
  86. if err != nil {
  87. return nil, false
  88. }
  89. clog.Debugf("[actor] create child. actorID = %s, targetPath = %v",
  90. childActor.ActorID(),
  91. m.TargetPath(),
  92. )
  93. return childActor, true
  94. }
  95. // create 创建联盟
  96. func (p *actor) leagueCreate(req *pb.CreateLeague) (*pb.I64, int32) {
  97. var (
  98. playerID = req.PlayerID
  99. leagueName = req.LeagueName
  100. leagueAbbName = req.LeagueAbbName
  101. flagBg = req.FlagBg
  102. flagIcon = req.FlagIcon
  103. )
  104. if playerID < 1 {
  105. return nil, code.IllegalArgument
  106. }
  107. // 检测联盟名称是否合法
  108. errCode := p.CheckLeagueName(leagueName)
  109. if code.IsFail(errCode) {
  110. return nil, errCode
  111. }
  112. // 检测简称是否合法
  113. errCode = p.CheckLeagueAbbName(leagueAbbName)
  114. if code.IsFail(errCode) {
  115. return nil, errCode
  116. }
  117. // 获取盟主职位ID
  118. leaderJobID := data.LeagueJob.GetLeaderJobID()
  119. if leaderJobID <= 0 {
  120. return nil, code.LeagueJobNotExist
  121. }
  122. leagueID := redis.GUID.NewLeagueID()
  123. leagueTable := db.NewMapLeagueTable(leagueID)
  124. // 联盟创建完成
  125. leagueTable.LeagueInfo.LeagueCreateFinish(playerID, leagueName, leagueAbbName, flagBg, flagIcon)
  126. leagueTable.Save2Queue()
  127. // 初始化联盟数据
  128. db.InitMapLeagueTables(leagueID)
  129. // 模块初始化
  130. mapFacade.LeagueServiceOnInit(leagueTable)
  131. //获取联盟成员列表
  132. leagueMemberTable, _ := db.GetMapLeagueMemberTable(leagueID)
  133. leagueMemberTable.LeagueMember.LeagueJoin(playerID)
  134. // 设置盟主职位&权限
  135. leagueMemberTable.SetLeagueMemberJob(leaderJobID, playerID)
  136. leagueMemberTable.SetLeagueJobPermission(leaderJobID, enum.LeaguePermissionss)
  137. leagueMemberTable.Save2Queue()
  138. // 更新联盟信息到redis
  139. updateLeagueInfo2Redis(leagueTable, leagueMemberTable, playerID)
  140. // 保存联盟ID
  141. p.leagueIDs = append(p.leagueIDs, leagueID)
  142. // 写入创建日志
  143. var (
  144. leagueLogTable, _ = db.GetMapLeagueLogTable(leagueID)
  145. playerName = cstring.ToString(playerID)
  146. )
  147. playerData := redis.Game.GetPlayerData(playerID, nameRedis.PlayerBaseFields...)
  148. if playerData != nil {
  149. playerName = playerData.PlayerName
  150. }
  151. leagueLogTable.AddLeagueLog(enum.Log_LeagueCreate, playerName)
  152. // 抛事件
  153. p.PostEvent(event.NewMapLeagueSync(leagueTable.LeagueID, leagueTable.ToMapLeague()))
  154. // 同步声望排行榜
  155. leagueBase.Service().SyncLeaguePrestigeRank(leagueTable, leagueMemberTable)
  156. resp := &pb.I64{Value: leagueID}
  157. return resp, code.OK
  158. }
  159. // 获取联盟列表
  160. func (p *actor) leagueList(req *pb.I64) (*pb.LeagueList, int32) {
  161. var (
  162. playerID = req.Value
  163. leagueList = []*pb.LeagueSearch{}
  164. )
  165. for _, leagueID := range p.leagueIDs {
  166. leagueTable, found := db.GetMapLeagueTable(leagueID)
  167. if !found {
  168. clog.Warnf("[leagueList]league not found. leagueID = %d", leagueID)
  169. continue
  170. }
  171. leagueList = append(leagueList, leagueTable.ToLeagueSearchProto(playerID))
  172. }
  173. rsp := &pb.LeagueList{
  174. Total: int32(len(leagueList)),
  175. List: leagueList,
  176. }
  177. return rsp, code.OK
  178. }
  179. // 模糊搜索联盟
  180. func (p *actor) leagueSearch(req *pb.Str) (*pb.LeagueList, int32) {
  181. var (
  182. keyword = strings.ToLower(req.Value)
  183. id = int64(0)
  184. )
  185. if cutils.IsNumeric(keyword) {
  186. id, _ = cstring.ToInt64(keyword)
  187. }
  188. leagueList := []*pb.LeagueSearch{}
  189. for _, leagueID := range p.leagueIDs {
  190. leagueTable, found := db.GetMapLeagueTable(leagueID)
  191. if !found {
  192. clog.Warnf("[leagueSearch]league not found. leagueID = %d", leagueID)
  193. continue
  194. }
  195. if keyword == "" || leagueTable.LeagueID == id ||
  196. strings.Contains(strings.ToLower(leagueTable.LeagueInfo.LeagueName), keyword) ||
  197. strings.Contains(strings.ToLower(leagueTable.LeagueInfo.LeagueAbbName), keyword) {
  198. leagueList = append(leagueList, leagueTable.ToLeagueSearchProto(0))
  199. }
  200. }
  201. rsp := &pb.LeagueList{
  202. Total: int32(len(leagueList)),
  203. List: leagueList,
  204. }
  205. return rsp, code.OK
  206. }
  207. // 获取联盟外交列表
  208. func (p *actor) diplomacyInfos(req *pb.None) (*pb.LeagueDiplomacyInfos, int32) {
  209. infos := &pb.LeagueDiplomacyInfos{}
  210. for _, leagueID := range p.leagueIDs {
  211. leagueTable, found := db.GetMapLeagueTable(leagueID)
  212. if !found {
  213. clog.Warnf("[leagueList]league not found. leagueID = %d", leagueID)
  214. continue
  215. }
  216. infos.List = append(infos.List, leagueTable.ToLeagueDiplomacyProto())
  217. }
  218. return infos, code.OK
  219. }
  220. // 联盟名称变更
  221. func (p *actor) leagueNameChange(req *pb.LeagueNameChange) int32 {
  222. var (
  223. playerID = req.PlayerID
  224. leagueID = req.LeagueID
  225. newLeagueName = req.NewName
  226. )
  227. // 获取联盟数据
  228. leagueTable, found := db.GetMapLeagueTable(leagueID)
  229. if !found {
  230. return code.LeagueNotExist
  231. }
  232. leagueMemberTable, found := db.GetMapLeagueMemberTable(leagueID)
  233. if !found {
  234. return code.LeagueMembersEmpty
  235. }
  236. oldLeagueName := leagueTable.LeagueInfo.LeagueName
  237. if ok := leagueMemberTable.LeagueMember.CheckPermission(playerID, enum.League_Permission_Diplomacy); !ok {
  238. return code.LeaguePermissionDenied
  239. }
  240. // 判断当前名称是否一致
  241. if newLeagueName == oldLeagueName {
  242. return code.LeagueNameNotChange
  243. }
  244. // 判断是否重名
  245. errCode := p.CheckLeagueName(newLeagueName)
  246. if code.IsFail(errCode) {
  247. return errCode
  248. }
  249. // 更新名称
  250. leagueTable.LeagueInfo.LeagueName = newLeagueName
  251. leagueTable.Save2Queue()
  252. memberIDList := leagueMemberTable.LeagueMember.GetLeagueMemberIDs()
  253. updateLeagueInfo2Redis(leagueTable, leagueMemberTable, memberIDList...)
  254. // 抛事件
  255. p.PostEvent(event.NewMapLeagueSync(leagueTable.LeagueID, leagueTable.ToMapLeague()))
  256. return code.OK
  257. }
  258. // 更新成员的联盟信息,联盟名称,简称,职位
  259. func updateLeagueInfo2Redis(leagueTable *db.MapLeagueTable, leagueMemberTable *db.MapLeagueMemberTable, memberIDList ...int64) {
  260. if len(memberIDList) <= 0 {
  261. return
  262. }
  263. var playerLeagueInfoList []*pb.PlayerLeagueInfo
  264. for _, memberID := range memberIDList {
  265. playerLeagueInfoList = append(playerLeagueInfoList, &pb.PlayerLeagueInfo{
  266. PlayerID: memberID,
  267. LeagueID: leagueTable.LeagueID,
  268. LeagueName: leagueTable.LeagueInfo.LeagueName,
  269. LeagueAbbName: leagueTable.LeagueInfo.LeagueAbbName,
  270. LeagueJob: leagueMemberTable.LeagueMember.GetLeagueMemberJob(memberID),
  271. })
  272. }
  273. redis.Game.UpdatePlayerDataLeagueInfo(playerLeagueInfoList...)
  274. }
  275. // 联盟简称变更
  276. func (p *actor) leagueAbbNameChange(req *pb.LeagueNameChange) int32 {
  277. var (
  278. playerID = req.PlayerID
  279. leagueID = req.LeagueID
  280. newLeagueAbbName = req.NewName
  281. )
  282. // 获取联盟数据
  283. leagueTable, found := db.GetMapLeagueTable(leagueID)
  284. if !found {
  285. return code.LeagueNotExist
  286. }
  287. leagueMemberTable, found := db.GetMapLeagueMemberTable(leagueID)
  288. if !found {
  289. return code.LeagueMembersEmpty
  290. }
  291. oldLeagueAbbName := leagueTable.LeagueInfo.LeagueAbbName
  292. if ok := leagueMemberTable.LeagueMember.CheckPermission(playerID, enum.League_Permission_Diplomacy); !ok {
  293. return code.LeaguePermissionDenied
  294. }
  295. // 判断当前简称是否一致
  296. if newLeagueAbbName == oldLeagueAbbName {
  297. return code.LeagueNameNotChange
  298. }
  299. // 判断是否重名
  300. errCode := p.CheckLeagueAbbName(newLeagueAbbName)
  301. if code.IsFail(errCode) {
  302. return errCode
  303. }
  304. // 更新名称
  305. leagueTable.LeagueInfo.LeagueAbbName = newLeagueAbbName
  306. leagueTable.Save2Queue()
  307. memberIDList := leagueMemberTable.LeagueMember.GetLeagueMemberIDs()
  308. updateLeagueInfo2Redis(leagueTable, leagueMemberTable, memberIDList...)
  309. // 抛事件
  310. p.PostEvent(event.NewMapLeagueSync(leagueTable.LeagueID, leagueTable.ToMapLeague()))
  311. return code.OK
  312. }
  313. // 检测联盟名称是否可用
  314. func (p *actor) CheckLeagueName(leagueName string) int32 {
  315. //检测联盟名称长度是否符合
  316. ok := data.Const.CheckLeagueNameLen(leagueName)
  317. if !ok {
  318. return code.LeagueNameLimit
  319. }
  320. //判断是否包含特殊符号 只能是字符、数字和中文
  321. if errCode := hasSpecialCharsForLeagueName(leagueName); code.IsFail(errCode) {
  322. return errCode
  323. }
  324. // 判断联盟名称是否存在
  325. for _, leagueID := range p.leagueIDs {
  326. leagueTable, found := db.GetMapLeagueTable(leagueID)
  327. if !found {
  328. continue
  329. }
  330. if leagueTable.LeagueInfo.LeagueName == leagueName {
  331. return code.LeagueNameExist
  332. }
  333. }
  334. return code.OK
  335. }
  336. // 检测联盟简称是否可用
  337. func (p *actor) CheckLeagueAbbName(leagueAbbName string) int32 {
  338. ok := data.Const.CheckLeagueAbbNameLen(leagueAbbName)
  339. if !ok {
  340. return code.LeagueAbbNameLimit
  341. }
  342. //判断是否包含特殊符号 只能是字符和数字 TODO 现在暂时一样
  343. if errCode := hasSpecialCharsForLeagueAbbName(leagueAbbName); code.IsFail(errCode) {
  344. return errCode
  345. }
  346. // 判断联盟名称是否存在
  347. for _, leagueID := range p.leagueIDs {
  348. leagueTable, found := db.GetMapLeagueTable(leagueID)
  349. if !found {
  350. continue
  351. }
  352. if leagueTable.LeagueInfo.LeagueAbbName == leagueAbbName {
  353. return code.LeagueAbbNameExist
  354. }
  355. }
  356. return code.OK
  357. }
  358. func hasSpecialCharsForLeagueName(leagueName string) int32 {
  359. for _, r := range leagueName {
  360. //判断是否为字母、数字 或者 汉字
  361. if !(unicode.IsLetter(r) || unicode.IsNumber(r) || unicode.In(r, unicode.Han)) {
  362. return code.LeagueNameHasSpecial
  363. }
  364. }
  365. return code.OK
  366. }
  367. func hasSpecialCharsForLeagueAbbName(leagueAbbName string) int32 {
  368. for _, r := range leagueAbbName {
  369. //判断是否为字母、数字 或者 汉字
  370. if !(unicode.IsLetter(r) || unicode.IsNumber(r)) {
  371. return code.LeagueNameHasSpecial
  372. }
  373. }
  374. return code.OK
  375. }