package exchange import ( actorRemote "f1-game/internal/actor_remote" "f1-game/internal/component/redis" "f1-game/internal/constant" "f1-game/internal/data" "f1-game/internal/enum" "f1-game/internal/extend/math" facade "f1-game/internal/facade" "f1-game/internal/pb" "f1-game/internal/types" "f1-game/nodes/map/internal/db" csnowflake "github.com/cherry-game/cherry/extend/snowflake" cstring "github.com/cherry-game/cherry/extend/string" ctime "github.com/cherry-game/cherry/extend/time" clog "github.com/cherry-game/cherry/logger" ) var srv = &service{} func Service() *service { return srv } type service struct { facade.PlayerServiceBase[*db.MapPlayerTable] } func (p *service) OnReset(playerTable *db.MapPlayerTable, time *ctime.CherryTime, byLogin bool) { playerTable.Exchange.Reset() playerTable.Save2Queue() } // 给买方发货 func (p *service) DeliverToBuyer(playerID int64, req *pb.PlayerExchangeItemDeliver) { var ( transID = req.TransID // 流水号 goodsID = req.GoodsID // 商品ID buyCount = req.Count // 购买数量 itemPrice = req.Price // 物品单价 wishPrice = req.WishPrice // 求购单价 mapPlayerTable = db.GetMapPlayerTable(playerID) exchangeGoodsRow, _ = data.ExchangeGoods.GetByID(goodsID) ) // 总价 sumPrice := buyCount * int64(itemPrice) // 交易物品ID itemID := exchangeGoodsRow.ItemID // 以邮件的方式发货 buyAssets := types.Assets{} // 如果是需要转成绑定资源就转成绑定资源 bindingItemID, ok := enum.UnBindingResourceMap[goodsID] if ok { goodsID = bindingItemID } buyAsset := types.NewAsset(goodsID, buyCount*int64(exchangeGoodsRow.UnitQty)) buyAssets.AddAsset(&buyAsset) // 求购差价 sumWishDiffPrice := int64(0) mailID := constant.MailID_MapExchangeBuySuccess mailParams := []string{ cstring.ToString(itemID), cstring.ToString(sumPrice), cstring.ToString(buyAsset.ID), cstring.ToString(buyAsset.Num), } // 求购购买的方式 if wishPrice > 0 { // 记录求购成功的次数 mapPlayerTable.Exchange.DailyWishCount++ mapPlayerTable.Save2Queue() // 单个单位的差价 wishDiffPrice := wishPrice - itemPrice if wishDiffPrice > 0 { sumWishDiffPrice = buyCount * int64(wishDiffPrice) // 返还求购差价 buyAssets.Add(itemID, sumWishDiffPrice) } mailID = constant.MailID_MapExchangeWishSuccess mailParams = []string{ cstring.ToString(itemID), cstring.ToString(sumPrice), cstring.ToString(buyAsset.ID), cstring.ToString(buyAsset.Num), cstring.ToString(sumWishDiffPrice), } } actorRemote.GameMail.SendMail(mapPlayerTable.GameNodeID, playerID, mailID, buyAssets, mailParams) // 交易的商品信息 buyGoodsAsset := types.NewAsset(goodsID, buyCount) exchangeLog := &pb.ExchangeLog{ LogID: csnowflake.NextID(), LogType: int32(enum.ExchangeLogType_Buy), Asset: buyGoodsAsset.ToProto(), Price: itemPrice, Time: ctime.Now().ToMillisecond(), } redis.Game.AddMapExchangeLog(mapPlayerTable.NodeID, playerID, enum.ExchangeLogType_Buy, int64(data.Const.ExchangeBuyLogSaveLimit), exchangeLog) clog.Infof("DeliverToBuyer success. playerID [%d], transID [%s], goodsID [%d], buyGoodsID [%d], itemID [%d], itemPrice [%d], sumPrice [%d], buyAssets [%+v], buyCount [%d], wishPrice [%d], sumWishDiffPrice [%d]", playerID, transID, exchangeGoodsRow.ID, goodsID, itemID, itemPrice, sumPrice, buyAssets, buyCount, wishPrice, sumWishDiffPrice) } // 给卖方发货 func (p *service) DeliverToSeller(playerID int64, req *pb.PlayerExchangeItemDeliver) { var ( transID = req.TransID goodsID = req.GoodsID mapPlayerTable = db.GetMapPlayerTable(playerID) sellCount = req.Count // 出售数量 itemPrice = req.Price // 物品单价 exchangeGoodsRow, _ = data.ExchangeGoods.GetByID(goodsID) ) // 交易物品ID itemID := exchangeGoodsRow.ItemID // 最低手续费 minFee := exchangeGoodsRow.MinFee // 总价 sumPrice := int32(sellCount) * itemPrice // 单价手续费 % feeRate := float32(exchangeGoodsRow.FeeRate) // 按照公式计算手续费 fee := math.Floor[float32, int32](float32(itemPrice) * feeRate / constant.PctBase * float32(sellCount)) fee = math.Max(fee, minFee) // 剩余的交易收益 remain := max(sumPrice-fee, 0) if remain < 1 { clog.Warnf("DeliverToSeller failed. playerID [%d], transID [%s], goodsID [%d], sumPrice [%d], fee [%d], remain [%d]", playerID, transID, goodsID, sumPrice, fee, remain) return } // 以邮件的方式发货 sellAssets := types.Assets{} sellAssets.Add(itemID, int64(remain)) // 总资源数量 sumSellCount := sellCount * int64(exchangeGoodsRow.UnitQty) mailParams := []string{ cstring.ToString(goodsID), cstring.ToString(sumSellCount), cstring.ToString(itemID), cstring.ToString(remain), } actorRemote.GameMail.SendMail(mapPlayerTable.GameNodeID, playerID, constant.MailID_MapExchangeSellSuccess, sellAssets, mailParams) // 交易的商品信息 sellGoodsAsset := types.NewAsset(goodsID, sellCount) exchangeLog := &pb.ExchangeLog{ LogID: csnowflake.NextID(), LogType: int32(enum.ExchangeLogType_Sell), Asset: sellGoodsAsset.ToProto(), Price: itemPrice, Fee: fee, Time: ctime.Now().ToMillisecond(), } redis.Game.AddMapExchangeLog(mapPlayerTable.NodeID, playerID, enum.ExchangeLogType_Sell, int64(data.Const.ExchangeSellLogSaveLimit), exchangeLog) clog.Infof("DeliverToSeller success. playerID [%d], transID [%s], goodsID [%d], itemID [%d], itemPrice [%d], sumPrice [%d], sellAssets [%+v], buyCount [%d], fee [%d]", playerID, transID, goodsID, itemID, itemPrice, sumPrice, sellAssets, sellCount, fee) }