league_storage.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. package mapLeague
  2. import (
  3. actorRemote "f1-game/internal/actor_remote"
  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. "f1-game/internal/extend/math"
  11. nameLocal "f1-game/internal/name/local"
  12. nameRedis "f1-game/internal/name/redis"
  13. nameRemote "f1-game/internal/name/remote"
  14. "f1-game/internal/pb"
  15. "f1-game/internal/sessions"
  16. "f1-game/internal/types"
  17. ao "f1-game/nodes/game/player/asset/origin"
  18. mapCall "f1-game/nodes/map/internal/call"
  19. "f1-game/nodes/map/internal/db"
  20. dbLeague "f1-game/nodes/map/internal/db/data/league"
  21. leagueMember "f1-game/nodes/map/league/member"
  22. leagueStorage "f1-game/nodes/map/league/storage"
  23. cstring "github.com/cherry-game/cherry/extend/string"
  24. cproto "github.com/cherry-game/cherry/net/proto"
  25. )
  26. func (p *actorLeague) initStorage() {
  27. p.Local().Register(nameLocal.MapLeague_StorageInfo, p.storageInfo)
  28. p.Local().Register(nameLocal.MapLeague_RatioUpdate, p.ratioUpdate)
  29. p.Local().Register(nameLocal.MapLeague_FundBonus, p.fundBonus)
  30. p.Remote().Register(nameRemote.MapLeague_AddRatioAssets, p.addRatioAssets)
  31. p.Remote().Register(nameRemote.MapLeague_AddAssets, p.addAssets)
  32. }
  33. // 获取仓库信息
  34. func (p *actorLeague) storageInfo(session *cproto.Session, _ *pb.None) {
  35. mapLeagueStorageTable := db.GetMapLeagueStorageTable(p.leagueID)
  36. p.Response(session, mapLeagueStorageTable.Storage.ToProto())
  37. }
  38. // 修改资源税率
  39. func (p *actorLeague) ratioUpdate(session *cproto.Session, req *pb.I32I32) {
  40. var (
  41. mapLeagueStorageTable = db.GetMapLeagueStorageTable(p.leagueID)
  42. currencyID = req.Key // 货币ID
  43. ratio = req.Value // 税率值
  44. playerID = sessions.GetPlayerID(session) // 操作的玩家ID
  45. )
  46. // 判断是否有权限
  47. if !p.leagueTable.LeagueInfo.IsLeader(playerID) {
  48. p.ResponseCode(session, code.LeagueNotLeader)
  49. return
  50. }
  51. // 税率调整次数不足
  52. if mapLeagueStorageTable.Storage.GetRatioRemainAdjustCount(currencyID) < 1 {
  53. p.ResponseCode(session, code.LeagueTaxRateNotEnough)
  54. return
  55. }
  56. leagueStorageRow, found := data.LeagueStorage.GetByID(currencyID)
  57. if !found {
  58. p.ResponseCode(session, code.ConfigNotFound_LeagueStorage)
  59. return
  60. }
  61. // 设值不满足条件
  62. if ratio < leagueStorageRow.MinRate || ratio > leagueStorageRow.MaxRate {
  63. p.ResponseCode(session, code.LeagueTaxRateValueError)
  64. return
  65. }
  66. storageRatio, found := mapLeagueStorageTable.Storage.RatioMap.Get(currencyID)
  67. if !found {
  68. // 没有就new一个
  69. storageRatio = dbLeague.NewStorageRatio(currencyID, leagueStorageRow.InitRate)
  70. mapLeagueStorageTable.Storage.RatioMap.Put(currencyID, storageRatio)
  71. }
  72. // 更新税率,返回旧的税率
  73. oldRatio := storageRatio.UpdateRatio(currencyID, ratio)
  74. mapLeagueStorageTable.Save2Queue()
  75. leagueLogTable, _ := db.GetMapLeagueLogTable(p.leagueID)
  76. // 获取玩家名称
  77. playerName := leagueMember.Service().GetPlayerName(playerID)
  78. if currencyID == enum.LeagueItemIDF {
  79. leagueLogTable.AddLeagueLog(enum.Log_LeagueFRatioUpdate, playerName, cstring.ToString(oldRatio), cstring.ToString(ratio))
  80. } else {
  81. leagueLogTable.AddLeagueLog(enum.Log_LeagueRateUpdate, playerName, cstring.ToString(currencyID), cstring.ToString(oldRatio), cstring.ToString(ratio))
  82. }
  83. leagueLogTable.Save2Queue()
  84. p.Response(session, storageRatio.ToProto())
  85. }
  86. // F币分红
  87. func (p *actorLeague) fundBonus(session *cproto.Session, req *pb.LeagueFundBonus) {
  88. var (
  89. mapLeagueStorageTable = db.GetMapLeagueStorageTable(p.leagueID)
  90. playerID = sessions.GetPlayerID(session) // 操作者
  91. memberIDList = req.MemberIDList // 成员ID列表
  92. memberNum = int64(len(memberIDList)) // 玩家数量
  93. totalFund = req.TotalFund // 分配的F币数量
  94. )
  95. if totalFund < 1 || memberNum < 1 {
  96. p.ResponseCode(session, code.IllegalArgument)
  97. return
  98. }
  99. // 判断是否有权限
  100. if !p.leagueTable.LeagueInfo.IsLeader(playerID) {
  101. p.ResponseCode(session, code.LeagueNotLeader)
  102. return
  103. }
  104. leagueStorageRow, found := data.LeagueStorage.GetByID(enum.LeagueItemIDF)
  105. if !found {
  106. p.ResponseCode(session, code.ConfigNotFound_LeagueStorage)
  107. return
  108. }
  109. // 最小值限制
  110. if totalFund < leagueStorageRow.MinFBonus {
  111. p.ResponseCode(session, code.LeagueFundBonusMinValueError)
  112. return
  113. }
  114. // 资源分配次数不足
  115. if mapLeagueStorageTable.Storage.GetFundBonusRemainCount() < 1 {
  116. p.ResponseCode(session, code.LeagueFundBonusRemainCountNotEnough)
  117. return
  118. }
  119. // F币不足
  120. if !p.isEnoughOne(enum.LeagueItemIDF, totalFund) {
  121. p.ResponseCode(session, code.LeagueFundBonusCountNotEnough)
  122. return
  123. }
  124. leaugeMemberTable, _ := db.GetMapLeagueMemberTable(p.leagueID)
  125. for _, sendPlayerID := range memberIDList {
  126. // 检查请求的公会成员ID是否存在
  127. if _, found := leaugeMemberTable.GetLeagueMember(sendPlayerID); !found {
  128. p.ResponseCode(session, code.LeagueMemberNotExist)
  129. return
  130. }
  131. }
  132. // 把余数部分去掉,不扣除了
  133. remainderCount := totalFund % memberNum
  134. if remainderCount > 0 {
  135. totalFund = totalFund - remainderCount
  136. }
  137. // 平均F币数量
  138. averageVal := totalFund / memberNum
  139. if averageVal < 1 {
  140. p.ResponseCode(session, code.LeagueFundBonusMinValueError)
  141. return
  142. }
  143. // 加上盟主的ID
  144. totalPlayerIDList := types.NewList(memberIDList...)
  145. totalPlayerIDList.Add(playerID)
  146. playerDataMap := redis.Game.GetPlayerDataMap(totalPlayerIDList, nameRedis.PlayerBaseFields...)
  147. if len(playerDataMap) == 0 {
  148. p.ResponseCode(session, code.DataNotFound)
  149. return
  150. }
  151. // 调整次数
  152. mapLeagueStorageTable.Storage.UpdateFundBonusCount()
  153. // 扣除F币
  154. cost := types.Assets{}
  155. cost.Add(enum.ItemIDF, totalFund)
  156. p.subAssets(cost)
  157. var (
  158. // 记录发放的成员名称列表
  159. playerNameList []string
  160. // 分配的F币
  161. rewards = types.Assets{}
  162. )
  163. rewards.Add(enum.ItemIDF, averageVal)
  164. for _, sendPlayerID := range memberIDList {
  165. // 累计分配数量
  166. member, found := leaugeMemberTable.GetLeagueMember(sendPlayerID)
  167. if !found {
  168. continue
  169. }
  170. // 记录成员每周分配的F币数量
  171. member.RecordWeeklyFund(averageVal)
  172. playerData, found := playerDataMap[sendPlayerID]
  173. if !found {
  174. continue
  175. }
  176. // 发送邮件
  177. actorRemote.GameMail.SendMail(playerData.GameNodeID, sendPlayerID, constant.MailID_LeagueFund, rewards, nil)
  178. // 记录发放的成员
  179. sendPlayerName := cstring.ToString(sendPlayerID)
  180. if found {
  181. sendPlayerName = playerData.PlayerName
  182. }
  183. playerNameList = append(playerNameList, sendPlayerName)
  184. }
  185. mapLeagueStorageTable.Save2Queue()
  186. leaugeMemberTable.Save2Queue()
  187. // 获取玩家名称
  188. playerName := playerDataMap[playerID].PlayerName
  189. leagueLogTable, _ := db.GetMapLeagueLogTable(p.leagueID)
  190. // TODO F币消耗日志模板需要增加
  191. leagueLogTable.AddLeagueLog(enum.Log_LeagueFundBonus, playerName, cstring.ToString(totalFund), cstring.ToString(playerNameList))
  192. leagueLogTable.Save2Queue()
  193. rsp := &pb.I32I64{
  194. Key: mapLeagueStorageTable.Storage.GetFundBonusRemainCount(),
  195. Value: mapLeagueStorageTable.Storage.GetFundBonusCount(),
  196. }
  197. p.Response(session, rsp)
  198. }
  199. // 增加联盟税收获取的资源
  200. func (p *actorLeague) addRatioAssets(req *pb.AddAssets) {
  201. var (
  202. mapLeagueStorageTable = db.GetMapLeagueStorageTable(p.leagueID)
  203. playerID = req.PlayerID // 交税玩家ID
  204. assets = req.Assets
  205. origin = req.Origin
  206. eventAssets = types.Assets{}
  207. )
  208. leagueLogTable, _ := db.GetMapLeagueLogTable(p.leagueID)
  209. playerData := leagueMember.Service().GetPlayerData(playerID)
  210. // TODO 收集每次应该只有一种资源,先预留多种资源的处理
  211. for _, asset := range assets {
  212. if !enum.IsMapCurrency(asset.Id) {
  213. p.Warn("addRatioAssets not league currency : %v", asset)
  214. continue
  215. }
  216. // 获取联盟资源ID
  217. leaugeItemID, found := enum.GetLeagueRatioItemID(asset.Id)
  218. if !found {
  219. p.Warn("addRatioAssets not league currency : %v", asset)
  220. continue
  221. }
  222. // 获取联盟资源当前税率
  223. ratio := mapLeagueStorageTable.Storage.GetRatio(leaugeItemID)
  224. if ratio == 0 {
  225. p.Warn("addRatioAssets ratio is 0 : %v", asset)
  226. continue
  227. }
  228. // 向上取整计算需要交的税
  229. leagueNum := math.Ceil[float64, int64](float64(asset.Num) * float64(ratio) / constant.PctBase)
  230. // 增加联盟资源
  231. p.addAsset(leaugeItemID, leagueNum)
  232. // 玩家交完税后的数量
  233. asset.Num = asset.Num - leagueNum
  234. playerAsset := types.Assets{}
  235. playerAsset.Add(asset.Id, asset.Num)
  236. mapCall.Player.AddAssets(playerID, playerAsset, ao.Get(origin))
  237. // F币日志处理
  238. if asset.Id == enum.LeagueItemIDF {
  239. leagueLogTable.AddLeagueLog(enum.Log_LeagueCollectResourceF, playerData.PlayerName, cstring.ToString(asset.Num), cstring.ToString(leagueNum))
  240. continue
  241. }
  242. // 其他资源日志处理
  243. leagueLogTable.AddLeagueLog(enum.Log_LeagueCollectResource, playerData.PlayerName, cstring.ToString(asset.Id), cstring.ToString(asset.Num), cstring.ToString(leagueNum))
  244. eventAssets.Add(asset.Id, asset.Num)
  245. }
  246. leagueLogTable.Save2Queue()
  247. // 发送玩家采集事件
  248. p.PostEvent(event.NewPlayerResGather(playerID, eventAssets))
  249. }
  250. // 检查联盟资源 单个
  251. func (p *actorLeague) isEnoughOne(currencyID int32, count int64) bool {
  252. assets := types.Assets{}
  253. assets.Add(currencyID, count)
  254. return p.isEnough(assets)
  255. }
  256. // 检查联盟资源
  257. func (p *actorLeague) isEnough(assets types.Assets) bool {
  258. mapLeagueStorageTable := db.GetMapLeagueStorageTable(p.leagueID)
  259. for _, asset := range assets {
  260. if !enum.IsLeagueCurrency(asset.ID) {
  261. p.Warn("isEnough not league currency : %v", asset)
  262. continue
  263. }
  264. if mapLeagueStorageTable.Storage.CurrencyMap.GetEntity(asset.ID).Num < asset.Num {
  265. return false
  266. }
  267. }
  268. return true
  269. }
  270. // 增加联盟货币 单个
  271. func (p *actorLeague) addAsset(currencyID int32, count int64) {
  272. if !enum.IsLeagueCurrency(currencyID) {
  273. p.Warn("addAsset not league currencyID: %v, count: %v", currencyID, count)
  274. return
  275. }
  276. mapLeagueStorageTable := db.GetMapLeagueStorageTable(p.leagueID)
  277. mapLeagueStorageTable.Storage.CurrencyMap.Increase(currencyID, count)
  278. mapLeagueStorageTable.Save2Queue()
  279. }
  280. // 增加联盟货币 多个
  281. func (p *actorLeague) addAssets(req *pb.AddAssets) {
  282. retAssets := types.Assets{}
  283. for _, asset := range req.Assets {
  284. if !enum.IsLeagueCurrency(asset.Id) {
  285. p.Warn("addAssets not league currency : %v", asset)
  286. continue
  287. }
  288. retAssets.Add(asset.Id, asset.Num)
  289. }
  290. leagueStorage.Service().AddAssets(p.leagueTable, retAssets)
  291. }
  292. // 扣除联盟资源
  293. func (p *actorLeague) subAssets(assets types.Assets) int32 {
  294. if !p.isEnough(assets) {
  295. p.Warn("subAssets not enough : %v", assets)
  296. return code.ItemNotEnough
  297. }
  298. mapLeagueStorageTable := db.GetMapLeagueStorageTable(p.leagueID)
  299. subAssets := types.Assets{}
  300. for _, asset := range assets {
  301. if !enum.IsLeagueCurrency(asset.ID) {
  302. p.Warn("subAssets not league currency : %v", asset)
  303. continue
  304. }
  305. mapLeagueStorageTable.Storage.CurrencyMap.Decrease(asset.ID, asset.Num)
  306. subAssets.AddAsset(asset)
  307. }
  308. mapLeagueStorageTable.Save2Queue()
  309. p.Debug("subAssets: %v", subAssets)
  310. return code.OK
  311. }