package asset import ( actorRemote "f1-game/internal/actor_remote" capp "f1-game/internal/cherry_app" "f1-game/internal/code" "f1-game/internal/data" "f1-game/internal/enum" "f1-game/internal/event" nameRoute "f1-game/internal/name/route" "f1-game/internal/sessions" "f1-game/internal/types" "f1-game/nodes/game/internal/db" ao "f1-game/nodes/game/player/asset/origin" clog "github.com/cherry-game/cherry/logger" ) // 构造一个资源对外服务类 var srv = &service{ typ: newServiceType(), } // Service 用于初始化资产接口 func Service() *service { return srv } type service struct { typ serviceType // 资源类型服务类(封装各种资源类型的细节) } func (p *service) Add(playerID int64, id int32, num int64, origin ao.Origin, push bool) (types.Assets, int32) { itemRow, found := data.Item.GetByID(id) if !found { return nil, code.ConfigNotFound_Item } parser, errCode := p.typ.get(itemRow.ParseType) if code.IsFail(errCode) { return nil, errCode } // 超过单次最大添加数量 if num > parser.MaxAddOnce() { return nil, code.ItemAddOnceNumLimit } addAsset := &types.Asset{ ID: id, Num: num, } retAssets := types.Assets{} if enum.IsMapCurrency(id) || enum.IsLeagueCurrency(id) { playerTable, _ := db.GetPlayerTable(playerID) if playerTable.Map.MapNodeID != "" { actorRemote.MapPlayer.AddAssets(playerTable.Map.MapNodeID, playerID, types.Assets{addAsset}, origin) retAssets.AddAsset(addAsset) } else { clog.Warnf("Add map assets fail: map node not found. playerID=%d, assets = %+v", playerID, addAsset) } } else { if errCode = parser.Add(playerID, addAsset, origin, &retAssets); code.IsOK(errCode) { assets := types.Assets{addAsset} // 发送系统消息事件 capp.PostEvent(event.NewChatSystemMsg(playerID, enum.ChatMsgType_reward, assets, nil)) capp.PostEvent(event.NewItemAdd(playerID, assets, origin)) if push { parser.Push(playerID, retAssets) } } } return retAssets, errCode } // Adds 添加资源 func (p *service) Adds(playerID int64, assets types.Assets, origin ao.Origin, push bool) (types.Assets, int32) { if len(assets) < 1 { return nil, code.AssetIsEmpty } var ( retAssets = types.Assets{} mapAssets = types.Assets{} gameAssets = types.Assets{} ) for _, asset := range assets { if enum.IsMapCurrency(asset.ID) || enum.IsLeagueCurrency(asset.ID) { mapAssets.Add(asset.ID, asset.Num) } else { gameAssets.Add(asset.ID, asset.Num) } } if mapAssets.Len() > 0 { playerTable, _ := db.GetPlayerTable(playerID) if playerTable.Map.MapNodeID != "" { actorRemote.MapPlayer.AddAssets(playerTable.Map.MapNodeID, playerID, mapAssets, origin) retAssets.AddAssets(mapAssets) } else { clog.Warnf("Add map assets fail: map node not found. playerID=%d, assets = %+v", playerID, mapAssets) } } if gameAssets.Len() > 0 { for _, asset := range gameAssets { parser, errCode := p.typ.getWithAssetID(asset.ID) if code.IsFail(errCode) { clog.Warnf("Add assets fail. playerID=%d, assets = %+v, code = %v", playerID, asset, errCode) continue } errCode = parser.Add(playerID, asset, origin, &retAssets) if code.IsFail(errCode) { clog.Warnf("Add assets fail. playerID=%d, assets = %+v, code = %v", playerID, retAssets, errCode) continue } } // 发送系统消息事件 capp.PostEvent(event.NewChatSystemMsg(playerID, enum.ChatMsgType_reward, gameAssets, nil)) capp.PostEvent(event.NewItemAdd(playerID, gameAssets, origin)) } // push by asset type if push { groupRetAssets, _ := p.groupAssets(retAssets) for parser, pushAssets := range groupRetAssets { parser.Push(playerID, pushAssets) } } return retAssets, code.OK } func (p *service) Sub(playerID int64, id int32, num int64, origin ao.Origin) (types.Assets, int32) { if num < 1 { return nil, code.ItemNumError } itemRow, found := data.Item.GetByID(id) if !found { return nil, code.ConfigNotFound_Item } parser, errCode := p.typ.get(itemRow.ParseType) if code.IsFail(errCode) { return nil, errCode } var addAssets types.Assets addAssets.Add(id, num) retAssets := types.Assets{} errCode = parser.Sub(playerID, addAssets, origin, &retAssets) if code.IsOK(errCode) { parser.Push(playerID, retAssets) } return retAssets, errCode } func (p *service) Subs(playerID int64, assets types.Assets, origin ao.Origin) (types.Assets, int32) { if len(assets) < 1 { return nil, code.AssetIsEmpty } assetsGroup, errCode := p.groupAssets(assets) if code.IsFail(errCode) { return nil, errCode } //检测资产数量是否满足 for parser, opAssets := range assetsGroup { for _, asset := range opAssets { if errCode = parser.IsEnough(playerID, asset); code.IsFail(errCode) { return nil, errCode } } } retAssets := types.Assets{} for parser, opAssets := range assetsGroup { errCode = parser.Sub(playerID, opAssets, origin, &retAssets) if code.IsFail(errCode) { clog.Warnf("Sub assets fail. playerID=%d, assets = %+v, code = %v", playerID, retAssets, errCode) continue } } // push by asset type groupRetAssets, _ := p.groupAssets(retAssets) for assetType, pushAssets := range groupRetAssets { assetType.Push(playerID, pushAssets) } return retAssets, code.OK } func (p *service) Enough(playerID int64, itemID int32, num int64) int32 { parser, errCode := p.typ.getWithAssetID(itemID) if code.IsFail(errCode) { return errCode } asset := types.NewAsset(itemID, num) errCode = parser.IsEnough(playerID, &asset) return errCode } func (p *service) IsAllEnough(playerID int64, assets types.Assets) int32 { for _, asset := range assets { if errCode := p.Enough(playerID, asset.ID, asset.Num); code.IsFail(errCode) { return errCode } } return code.OK } func (p *service) Get(playerID int64, assetID int32) int64 { parser, errCode := p.typ.getWithAssetID(assetID) if code.IsFail(errCode) { return 0 } return parser.Get(playerID, assetID) } // Check 检查资产类型 func (p *service) Check(assets types.Assets) int32 { for _, asset := range assets { _, errCode := p.typ.getWithAssetID(asset.ID) if code.IsFail(errCode) { return errCode } } return code.OK } func (p *service) groupAssets(assets types.Assets) (map[typeParser]types.Assets, int32) { groupMap := make(map[typeParser]types.Assets) for _, asset := range assets { effector, errCode := p.typ.getWithAssetID(asset.ID) if code.IsFail(errCode) { return nil, errCode } assetsSlice, found := groupMap[effector] if !found { assetsSlice = make(types.Assets, 0) } assetsSlice = append(assetsSlice, asset) groupMap[effector] = assetsSlice } return groupMap, code.OK } func (p *service) RewardPush(playerID int64, assets types.Assets) { sessions.PushPlayer(playerID, nameRoute.PushGamePlayer_Reward, assets.ToAssetListProto()) }