| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596 |
- package mapPlayer
- import (
- actorRemote "f1-game/internal/actor_remote"
- "f1-game/internal/code"
- "f1-game/internal/component/redis"
- "f1-game/internal/constant"
- "f1-game/internal/data"
- "f1-game/internal/enum"
- nameLocal "f1-game/internal/name/local"
- nameRemote "f1-game/internal/name/remote"
- "f1-game/internal/pb"
- "f1-game/internal/types"
- ao "f1-game/nodes/game/player/asset/origin"
- mapCall "f1-game/nodes/map/internal/call"
- "f1-game/nodes/map/internal/db"
- mapFacade "f1-game/nodes/map/internal/facade"
- "f1-game/nodes/map/player/exchange"
- cstring "github.com/cherry-game/cherry/extend/string"
- cproto "github.com/cherry-game/cherry/net/proto"
- )
- func (p *actorPlayer) initExchange() {
- p.Local().Register(nameLocal.MapPlayer_ExchangeSlotUnlock, p.exchangeSlotUnlock)
- p.Local().Register(nameLocal.MapPlayer_ExchangeHistoryPrice, p.exchangeHistoryPrice)
- p.Local().Register(nameLocal.MapPlayer_ExchangeItem, p.exchangeItem)
- p.Local().Register(nameLocal.MapPlayer_ExchangeBuyItem, p.exchangeBuyItem)
- p.Local().Register(nameLocal.MapPlayer_ExchangeQuery, p.exchangeQuery)
- p.Local().Register(nameLocal.MapPlayer_ExchangeMyItems, p.exchangeMyItems)
- p.Local().Register(nameLocal.MapPlayer_ExchangeItemUpdate, p.exchangeItemUpdate)
- p.Local().Register(nameLocal.MapPlayer_ExchangeLog, p.exchangeLog)
- p.Remote().Register(nameRemote.MapPlayerExchange_ItemDeliver, p.exchangeItemDeliver)
- p.Remote().Register(nameRemote.MapPlayerExchange_ItemRetrieve, p.exchangeItemRetrieve)
- p.Remote().Register(nameRemote.MapPlayerExchange_ItemCanceled, p.exchangeBuyItemCanceled)
- p.Remote().Register(nameRemote.MapPlayerExchange_ItemRemove, p.exchangeBuyItemRemove)
- }
- // 交易所货柜解锁
- func (p *actorPlayer) exchangeSlotUnlock(session *cproto.Session, req *pb.I32) {
- actType := enum.ExchangeActType(req.Value)
- if !enum.IsExchangeActType(actType) {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- exchangeSlotRow, found := data.ExchangeSlot.GetBySlotTypeExchangeType(actType, enum.ExchangeType_Map)
- if !found {
- p.ResponseCode(session, code.ConfigNotFound_ExchangeSlot)
- return
- }
- playerTable := db.GetMapPlayerTable(p.playerID)
- switch actType {
- case enum.ExchangeActType_Sell:
- {
- nowCount := playerTable.Exchange.SellingUnlockedSlots
- if int(nowCount) >= len(exchangeSlotRow.Cost) {
- p.ResponseCode(session, code.ExchangeSlotSellMaxLimit)
- return
- }
- unlockCost := exchangeSlotRow.Cost[nowCount]
- if unlockCost.ID > 0 && unlockCost.Num > 0 {
- // 检查解锁消耗是否足够,只判断非地图的资源
- assets := types.Assets{unlockCost}
- if _, errCode := actorRemote.GamePlayer.AssetSub(playerTable.GameNodeID, p.playerID, assets, ao.ExchangeSellUnlockCost); code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- }
- // 增加出售货柜解锁数量
- playerTable.Exchange.SellingUnlockedSlots++
- playerTable.Save2Queue()
- p.Debug("exchangeSlotUnlock success. actType %v, sellingUnlockedSlots [%d->%d]", actType, nowCount, playerTable.Exchange.SellingUnlockedSlots)
- p.Response(session, &pb.I32I32{
- Key: int32(actType),
- Value: playerTable.Exchange.SellingUnlockedSlots,
- })
- }
- case enum.ExchangeActType_Wish:
- {
- nowCount := playerTable.Exchange.WishingUnlockedSlots
- if int(nowCount) >= len(exchangeSlotRow.Cost) {
- p.ResponseCode(session, code.ExchangeSlotWishMaxLimit)
- return
- }
- unlockCost := exchangeSlotRow.Cost[nowCount]
- if unlockCost.ID > 0 && unlockCost.Num > 0 {
- // 检查解锁消耗是否足够,只判断非地图的资源
- assets := types.Assets{unlockCost}
- if _, errCode := actorRemote.GamePlayer.AssetSub(playerTable.GameNodeID, p.playerID, assets, ao.ExchangeWishUnlockCost); code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- }
- // 增加求购货柜解锁数量
- playerTable.Exchange.WishingUnlockedSlots++
- playerTable.Save2Queue()
- p.Debug("exchangeSlotUnlock success. actType %v, buyingUnlockedSlots [%d->%d]", actType, nowCount, playerTable.Exchange.WishingUnlockedSlots)
- p.Response(session, &pb.I32I32{
- Key: int32(actType),
- Value: playerTable.Exchange.WishingUnlockedSlots,
- })
- }
- }
- }
- // 获取物品的历史求购价格
- func (p *actorPlayer) exchangeHistoryPrice(session *cproto.Session, req *pb.I32) {
- itemID := req.Value
- if itemID < 1 {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- if !data.ExchangeGoods.ContainID(itemID) {
- p.ResponseCode(session, code.ConfigNotFound_ExchangeGoods)
- return
- }
- historyPrices, errCode := mapCall.Exchange.HistoryPrice(itemID)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- p.Response(session, historyPrices)
- p.Debug("exchangeHistoryPrice success. itemID %d, historyPrices %v", itemID, historyPrices)
- }
- // 出售或求购资源和材料
- func (p *actorPlayer) exchangeItem(session *cproto.Session, req *pb.ExchangeItem) {
- var (
- actType = enum.ExchangeActType(req.ActType)
- assetProto = req.Asset
- price = req.Price
- )
- if !enum.IsExchangeActType(actType) {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- if assetProto == nil || assetProto.Id < 1 || assetProto.Num < 1 || price < 1 {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- exchangeGoodsRow, found := data.ExchangeGoods.GetByID(assetProto.Id)
- if !found {
- p.ResponseCode(session, code.ConfigNotFound_ExchangeGoods)
- return
- }
- if exchangeGoodsRow.ExchangeType != enum.ExchangeType_Map {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- // 地图交易所只交易资源类型的商品
- if exchangeGoodsRow.ItemType != enum.ExchangeItemType_Resource {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- // 不允许交易非地图资源
- if !enum.IsMapCurrency(assetProto.Id) {
- p.ResponseCode(session, code.ExchangeItemConfigError)
- return
- }
- // 交易最低手续费不能低于单价
- if exchangeGoodsRow.MinFee > exchangeGoodsRow.MinPrice {
- p.ResponseCode(session, code.ExchangeMinFeeConfigError)
- return
- }
- // 判断物品的单价是否合法
- if price < exchangeGoodsRow.MinPrice || price > exchangeGoodsRow.MaxPrice {
- p.ResponseCode(session, code.ExchangeItemPriceIllegal)
- return
- }
- var (
- mapPlayerTable = db.GetMapPlayerTable(p.playerID)
- playerExchangeItem = &pb.PlayerExchangeItem{
- PlayerID: p.playerID,
- GameNodeID: mapPlayerTable.GameNodeID,
- ItemInfo: req,
- }
- )
- switch actType {
- case enum.ExchangeActType_Sell:
- // 判断交易数量是否合法
- if assetProto.Num < int64(exchangeGoodsRow.MinCount) ||
- assetProto.Num > int64(exchangeGoodsRow.MaxCount) {
- p.ResponseCode(session, code.ExchangeItemQtyIllegal)
- return
- }
- if !mapPlayerTable.Exchange.IsSlotsEnough(actType) {
- p.ResponseCode(session, code.ExchangeSlotSellNotEnough)
- return
- }
- // 数量单位
- unitQty := exchangeGoodsRow.UnitQty
- // 总数量
- sumCount := assetProto.Num * int64(unitQty)
- // 出售就判断自身是否有足够的物品
- if !mapFacade.Storage.IsEnough(p.playerID, assetProto.Id, sumCount) {
- p.ResponseCode(session, code.ExchangeCountNotEnough)
- return
- }
- retExchangeDetail, errCode := mapCall.Exchange.ExchangeItem(playerExchangeItem)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- mapPlayerTable.Exchange.Sells.Add(retExchangeDetail.TransactionID)
- mapPlayerTable.Save2Queue()
- // 扣除物品
- mapFacade.Storage.AssetSubOne(p.playerID, assetProto.Id, sumCount, ao.ExchangeSellItemCost, true)
- p.Response(session, retExchangeDetail)
- p.Debug("exchangeItem success. transID [%s]", retExchangeDetail.TransactionID)
- case enum.ExchangeActType_Wish:
- if !mapPlayerTable.Exchange.IsSlotsEnough(actType) {
- p.ResponseCode(session, code.ExchangeSlotWishNotEnough)
- return
- }
- // 计算总价
- sumPrice := int64(price) * assetProto.Num
- var (
- asset = types.NewAsset(exchangeGoodsRow.ItemID, sumPrice)
- assets = types.Assets{&asset}
- )
- // 求购就判断自身是否有足够的交易道具
- if errCode := actorRemote.GamePlayer.AssetCheck(mapPlayerTable.GameNodeID, p.playerID, assets); code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- // 判断每日求购次数是否已达上限, 如果已达上限则标记为已达上限,不进行匹配
- if mapPlayerTable.Exchange.DailyWishCount >= data.Const.ExchangeDailyWishLimit {
- playerExchangeItem.IsWishLimit = true
- }
- retExchangeDetail, errCode := mapCall.Exchange.ExchangeItem(playerExchangeItem)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- mapPlayerTable.Exchange.Wishs.Add(retExchangeDetail.TransactionID)
- mapPlayerTable.Save2Queue()
- // 扣除求购消耗
- if _, errCode := actorRemote.GamePlayer.AssetSub(mapPlayerTable.GameNodeID, p.playerID, assets, ao.ExchangeWishItemCost); code.IsFail(errCode) {
- p.Warn("exchangeItem AssetSub errCode [%d], transID [%s]", errCode, retExchangeDetail.TransactionID)
- p.ResponseCode(session, errCode)
- return
- }
- p.Response(session, retExchangeDetail)
- p.Debug("exchangeItem success. transID [%s]", retExchangeDetail.TransactionID)
- }
- }
- // 购买物品
- func (p *actorPlayer) exchangeBuyItem(session *cproto.Session, req *pb.I32Str) {
- var (
- transID = req.Value // 交易流水号
- count = req.Key // 数量
- )
- if cstring.IsBlank(transID) || count < 1 {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- mapPlayerTable := db.GetMapPlayerTable(p.playerID)
- // 判断是不是自己的交易流水号
- if mapPlayerTable.Exchange.IsOwnTransaction(transID) {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- // 判断每日购买次数是否已达上限
- if mapPlayerTable.Exchange.DailyBuyCount >= data.Const.ExchangeDailyBuyLimit {
- p.ResponseCode(session, code.ExchangeDailyBuyCountLimit)
- return
- }
- buyReq := &pb.PlayerExchangeBuyItem{
- PlayerID: p.playerID,
- GameNodeID: mapPlayerTable.GameNodeID,
- TransID: transID,
- Count: int64(count),
- }
- retResult, errCode := mapCall.Exchange.BuyItem(buyReq)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- if code.IsOK(retResult.Code) {
- // 记录每日购买次数
- mapPlayerTable.Exchange.DailyBuyCount++
- mapPlayerTable.Save2Queue()
- p.Debug("exchangeBuyItem success. transID [%s], count [%d]", transID, count)
- }
- p.Response(session, retResult)
- }
- // 根据条件查询地图交易所的商品列表
- func (p *actorPlayer) exchangeQuery(session *cproto.Session, req *pb.ExchangeQueryFilter) {
- pageNum := req.PageNum // 页数
- if pageNum < 1 {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- itemDetails, errCode := mapCall.Exchange.QueryItem(req)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- p.Response(session, itemDetails)
- p.Debug("exchangeQuery success. itemDetail len [%d]", len(itemDetails.List))
- }
- // 获取自己的商品信息
- func (p *actorPlayer) exchangeMyItems(session *cproto.Session, req *pb.I32) {
- actType := enum.ExchangeActType(req.Value)
- if !enum.IsExchangeActType(actType) {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- mapPlayerTable := db.GetMapPlayerTable(p.playerID)
- rsp := &pb.MyExchangeItems{
- ActType: req.Value,
- UnlockedSlots: mapPlayerTable.Exchange.GetUnlockSlots(actType),
- }
- transIDList := mapPlayerTable.Exchange.GetItemsByActType(actType)
- if transIDList.IsEmpty() {
- p.Response(session, rsp)
- return
- }
- retItemList, errCode := mapCall.Exchange.MyItems(p.playerID, actType, transIDList)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- rsp.List = retItemList.List
- p.Response(session, rsp)
- p.Debug("exchangeMyItems success. actType [%d], itemList [%+v]", actType, transIDList)
- }
- // 手动更新商品状态,包括下架,重新下架,取回
- func (p *actorPlayer) exchangeItemUpdate(session *cproto.Session, req *pb.I32Str) {
- var (
- updateType = enum.ExchangeUpdateType(req.Key) // 更新类型
- transID = req.Value // 流水号
- )
- if !enum.IsExchangeUpdateType(updateType) {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- if cstring.IsBlank(transID) {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- mapPlayerTable := db.GetMapPlayerTable(p.playerID)
- actType := mapPlayerTable.Exchange.GetActTypeByTransID(transID)
- if actType == 0 {
- p.ResponseCode(session, code.ExchangeItemNotFound)
- return
- }
- // 是否已达每日求购次数上限做一个标记
- isWishLimit := false
- if updateType == enum.ExchangeUpdateType_ReList {
- // 判断每日求购次数是否已达上限, 如果已达上限则标记为已达上限,不进行匹配
- if mapPlayerTable.Exchange.DailyWishCount >= data.Const.ExchangeDailyWishLimit {
- isWishLimit = true
- }
- }
- errCode := mapCall.Exchange.ItemUpdate(p.playerID, updateType, actType, transID, isWishLimit)
- if code.IsFail(errCode) {
- p.ResponseCode(session, errCode)
- return
- }
- // 只有取回需要删除记录
- if updateType == enum.ExchangeUpdateType_Retrieve {
- switch actType {
- case enum.ExchangeActType_Wish:
- mapPlayerTable.Exchange.Wishs.RemoveValue(transID)
- case enum.ExchangeActType_Sell:
- mapPlayerTable.Exchange.Sells.RemoveValue(transID)
- }
- mapPlayerTable.Save2Queue()
- }
- p.ResponseCode(session, code.OK)
- p.Debug("exchangeItemUpdate success. updateType [%d], transID [%s]", updateType, transID)
- }
- // 获取交易日志
- func (p *actorPlayer) exchangeLog(session *cproto.Session, req *pb.I32I64) {
- var (
- logType = enum.ExchangeLogType(req.Key) // 交易日志类型
- lastLogID = req.Value // 最近的日志ID
- )
- if lastLogID < 0 {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- if !enum.IsExchangeLogType(logType) {
- p.ResponseCode(session, code.IllegalArgument)
- return
- }
- logList := redis.Game.GetMapExchangeLogList(p.App().NodeID(), p.playerID, logType, lastLogID)
- if logList == nil {
- p.Response(session, &pb.ExchangeLogList{})
- return
- }
- p.Response(session, logList)
- p.Debug("exchangeLog success. logType [%d], lastLogID [%d], logList size [%d]", logType, lastLogID, len(logList.List))
- }
- // 发货接口
- func (p *actorPlayer) exchangeItemDeliver(req *pb.PlayerExchangeItemDeliver) {
- // 自己是买方
- if req.IsBuyer {
- exchange.Service().DeliverToBuyer(p.playerID, req)
- } else { // 自己是卖方
- exchange.Service().DeliverToSeller(p.playerID, req)
- }
- }
- // 取回
- func (p *actorPlayer) exchangeItemRetrieve(req *pb.ExchangeDetail) {
- var (
- actType = enum.ExchangeActType(req.ActType)
- transID = req.TransactionID
- mapPlayerTable = db.GetMapPlayerTable(p.playerID)
- asset = req.Asset
- exchangeGoodsRow, _ = data.ExchangeGoods.GetByID(asset.Id)
- )
- switch actType {
- case enum.ExchangeActType_Sell:
- {
- // 数量单位
- unitQty := exchangeGoodsRow.UnitQty
- // 总数量
- sumCount := asset.Num * int64(unitQty)
- // 返还出售资源
- mapFacade.Storage.AssetAddOne(p.playerID, asset.Id, sumCount, ao.ExchangeItemSellRetrieve, true)
- // 删除出售关联数据
- mapPlayerTable.Exchange.Sells.RemoveValue(transID)
- mapPlayerTable.Save2Queue()
- mailParams := []string{
- cstring.ToString(asset.Id),
- cstring.ToString(sumCount),
- }
- actorRemote.GameMail.SendMail(mapPlayerTable.GameNodeID, p.playerID, constant.MailID_MapExchangeRetrieve, nil, mailParams)
- p.Debug("exchangeItemRetrieve success. transID [%s], asset [%+v], sumCount [%d]", transID, asset, sumCount)
- }
- case enum.ExchangeActType_Wish:
- {
- // 交易物品ID
- itemID := exchangeGoodsRow.ItemID
- // 单价
- itemPrice := req.Price
- // 总价
- sumItemPrice := asset.Num * int64(itemPrice)
- wishAssets := types.Assets{}
- wishAssets.Add(itemID, int64(sumItemPrice))
- // 返还求购资源
- actorRemote.GamePlayer.AssetAddAsync(mapPlayerTable.GameNodeID, p.playerID, wishAssets, ao.ExchangeItemWishRetrieve)
- // 删除求购关联数据
- mapPlayerTable.Exchange.Wishs.RemoveValue(transID)
- mapPlayerTable.Save2Queue()
- mailParams := []string{
- cstring.ToString(itemID),
- cstring.ToString(sumItemPrice),
- }
- actorRemote.GameMail.SendMail(mapPlayerTable.GameNodeID, p.playerID, constant.MailID_MapExchangeWishCancel, nil, mailParams)
- p.Debug("exchangeItemRetrieve success. transID [%s], wishAssets [%+v]", transID, wishAssets)
- }
- }
- }
- // 系统通知商品下架
- func (p *actorPlayer) exchangeBuyItemCanceled(req *pb.ExchangeDetail) {
- var (
- actType = enum.ExchangeActType(req.ActType)
- mapPlayerTable = db.GetMapPlayerTable(p.playerID)
- asset = req.Asset
- exchangeGoodsRow, _ = data.ExchangeGoods.GetByID(asset.Id)
- )
- // 求购需要发邮件通知
- if actType == enum.ExchangeActType_Wish {
- // 求购总数量
- sumCount := asset.Num * int64(exchangeGoodsRow.UnitQty)
- mailParams := []string{
- cstring.ToString(asset.Id),
- cstring.ToString(sumCount),
- }
- actorRemote.GameMail.SendMail(mapPlayerTable.GameNodeID, p.playerID, constant.MailID_MapExchangeWishTimeout, nil, mailParams)
- }
- p.Debug("exchangeBuyItemCanceled success. actType [%d] transID [%s]", actType, req.TransactionID)
- }
- // 同步删除交易流水号
- func (p *actorPlayer) exchangeBuyItemRemove(req *pb.I32Str) {
- var (
- transID = req.Value
- actType = enum.ExchangeActType(req.Key)
- mapPlayerTable = db.GetMapPlayerTable(p.playerID)
- )
- switch actType {
- case enum.ExchangeActType_Sell:
- mapPlayerTable.Exchange.Sells.RemoveValue(transID)
- mapPlayerTable.Save2Queue()
- case enum.ExchangeActType_Wish:
- mapPlayerTable.Exchange.Wishs.RemoveValue(transID)
- mapPlayerTable.Save2Queue()
- }
- p.Debug("exchangeBuyItemRemove success. actType [%d], transID [%s]", actType, transID)
- }
|