修改目标
- 价格范围不再散落硬编码,统一收进
ConfigInfo.ini
- 上架、改价、成交到账统一走服务端校验
- 改价链改成先校验、再扣费、失败回退
- 售出元宝领取、取回、过期取回补空值防御,避免缓存失效直接炸服务
- 客户端不改,服务端兜底
修改文件
/home/ubuntu/Game2/configs/ConfigInfo.ini
/home/ubuntu/Game2/lualib/ybmarket_helper.lua
/home/ubuntu/Game2/services/msgagent.lua
/home/ubuntu/Game2/services/scene/scenecore.lua
/home/ubuntu/Game2/services/ybexchange/ybexchange_core.lua
/home/ubuntu/Game2/services/scene/obj/human.lua
1. 配置收口
文件:/home/ubuntu/Game2/configs/ConfigInfo.ini
[YBMarket] ;元宝交易市场
MinPrice=2 ;玩家最低上架价格
MaxPrice=200000 ;玩家最高上架价格
SellerTaxRatePct=2 ;成交后卖家到账税率百分比
ListingFeeRate=30 ;上架/改价手续费倍率(价格或差价*倍率)
说明:
MinPrice / MaxPrice 控制上架和改价范围
SellerTaxRatePct 控制卖家最终到账税率
ListingFeeRate 控制上架手续费、涨价补差手续费
- 手续费规则:首次上架按价格收一次,涨价补差,降价不返还
2. 新增公共 helper
文件:/home/ubuntu/Game2/lualib/ybmarket_helper.lua
***付费内容***
3. 修正扣费函数
文件:/home/ubuntu/Game2/services/scene/obj/human.lua
function human:cost_money_with_priority(cost, reason, extra)
assert(cost >= 1, cost)
local money = self:get_money()
local jiaozi = self:get_jiaozi()
if money + jiaozi < cost then
return false, 0, 0
end
local cost_jiaozi = 0
local cost_money = 0
if jiaozi >= cost then
local ok = self:set_jiaozi(jiaozi - cost, reason, extra)
if not ok then
return false, 0, 0
end
cost_jiaozi = cost
else
local diff = cost - jiaozi
local ok_jiaozi = self:set_jiaozi(0, reason, extra)
if not ok_jiaozi then
return false, 0, 0
end
local ok_money = self:set_money(money - diff, reason, extra)
if not ok_money then
self:set_jiaozi(jiaozi, reason, extra)
return false, 0, 0
end
cost_jiaozi = jiaozi
cost_money = diff
end
return true, cost_jiaozi, cost_money
end
4. 上架入口改成统一价格校验
文件:/home/ubuntu/Game2/services/msgagent.lua
function request:CGAuctionSell()
...
local ok, err_msg = ybmarket_helper.validate_price(self.price)
if not ok then
ma_func:notify_tips(err_msg)
return
end
...
local serial, err_msg = skynet.call(".Ybexchange", "lua", "sell", auction_request)
if not serial then
if err_msg then
ma_func:notify_tips(err_msg)
end
return
end
...
end
文件:/home/ubuntu/Game2/services/scene/scenecore.lua
function scenecore:auction_sell_before_check(who, auction_sell)
local ret_args
local human = self:get_obj_by_id(who)
if not human then return end
local ok, err_msg = ybmarket_helper.validate_price(auction_sell.price)
if not ok then
human:notify_tips(err_msg)
return
end
...
local money = human:get_money() + human:get_jiaozi()
local need_cost = ybmarket_helper.calc_listing_fee(auction_sell.price)
if money < need_cost then
human:notify_tips("手续费不足,上架失败")
return
end
return table.unpack(ret_args)
end
function scenecore:auction_sell_after_remove(who, auction_sell)
...
human:cost_money_with_priority(ybmarket_helper.calc_listing_fee(auction_sell.price), "交易行寄售上架手续")
return index
end
文件:/home/ubuntu/Game2/services/ybexchange/ybexchange_core.lua
function ybexchange_core:sell(request)
...
local ok, err_msg = ybmarket_helper.validate_price(request.price)
if not ok then
return false, err_msg
end
...
end
5. 改价链重做
规则:
- 涨价时补差价手续费
- 降价时不返还手续费
- 改价失败时,已扣的手续费必须回退
5.1 入口层
文件:/home/ubuntu/Game2/services/msgagent.lua
***付费内容***
5.2 场景层
文件:/home/ubuntu/Game2/services/scene/scenecore.lua
function scenecore:auction_modify_before_check(who, merchadise, new_price)
local human = self:get_obj_by_id(who)
if not human then
return false, "角色不存在"
end
if not merchadise then
return false, "寄售信息已失效,请刷新后重试"
end
if merchadise.status ~= "on_sale" then
return false, "寄售信息已失效,请刷新后重试"
end
local ok, err_msg = ybmarket_helper.validate_price(new_price)
if not ok then
return false, err_msg
end
local diff = new_price - merchadise.price
if diff <= 0 then
return true
end
local need_cost = ybmarket_helper.calc_listing_fee(diff)
if not human:check_money_with_priority(need_cost) then
return false, "手续费不足,改价失败"
end
return true
end
function scenecore:auction_modify_after_do(who, old_price, new_price)
local human = self:get_obj_by_id(who)
if not human then
return false, 0, 0
end
local diff = new_price - old_price
if diff <= 0 then
return true, 0, 0
end
return human:cost_money_with_priority(ybmarket_helper.calc_listing_fee(diff), "交易行寄售上架手续")
end
function scenecore:auction_modify_refund_after_fail(who, refund_jiaozi, refund_money)
local human = self:get_obj_by_id(who)
if not human then
return false
end
refund_jiaozi = refund_jiaozi or 0
refund_money = refund_money or 0
if refund_jiaozi > 0 then
local ok = human:set_jiaozi(human:get_jiaozi() + refund_jiaozi, "交易行寄售改价手续费回退")
if not ok then
return false
end
end
if refund_money > 0 then
local ok = human:set_money(human:get_money() + refund_money, "交易行寄售改价手续费回退")
if not ok then
return false
end
end
return true
end
5.3 数据层
文件:/home/ubuntu/Game2/services/ybexchange/ybexchange_core.lua
function ybexchange_core:modify(merchadise, request)
if not merchadise then
return false, "寄售信息已失效,请刷新后重试"
end
if not request or request.price == nil then
return false, "价格参数异常"
end
local ok, err_msg = ybmarket_helper.validate_price(request.price)
if not ok then
return false, err_msg
end
local coll_name = "ybmarket"
local query_tbl = {seller_guid = merchadise.seller_guid, status = "on_sale"}
...
local ok, err, result = skynet.call(".db", "lua", "safe_update", {
collection = coll_name,
selector = query_tbl,
update = updater,
upsert = false
})
...
end
6. 领取售出元宝 / 取回 / 过期取回 防崩
6.1 统一处理本地缓存
文件:/home/ubuntu/Game2/services/msgagent.lua
local function get_auction_box_merchadise(auction_type, index, offset)
if not auction_box_list then
return nil
end
local merchadise_list
local list_index
if auction_type == 1 then
merchadise_list = auction_box_list.pets
list_index = offset and (index + offset) or (index - 10)
else
merchadise_list = auction_box_list.items
list_index = offset and (index + offset) or index
end
if not merchadise_list or not list_index or list_index < 1 then
return nil, merchadise_list, list_index
end
return merchadise_list[list_index], merchadise_list, list_index
end
local function remove_auction_box_merchadise(auction_type, index, offset)
local merchadise, merchadise_list, list_index = get_auction_box_merchadise(auction_type, index, offset)
if merchadise_list and list_index and list_index >= 1 and list_index <= #merchadise_list then
table.remove(merchadise_list, list_index)
end
return merchadise
end
6.2 领取售出元宝
文件:/home/ubuntu/Game2/services/msgagent.lua
function request:CGAuctionGetYB()
if not auction_box_list then
ma_func:notify_tips("寄售信息已失效,请刷新后重试")
return
end
local merchadise = get_auction_box_merchadise(self.type, self.index)
if not merchadise then
ma_func:notify_tips("寄售信息已失效,请刷新后重试")
return
end
local item_name, yuanbao, err_msg = skynet.call(".Ybexchange", "lua", "get_sold_out_yuanbao", merchadise)
if item_name == nil and yuanbao == nil then
remove_auction_box_merchadise(self.type, self.index)
ma_func:notify_tips(err_msg or "寄售信息已失效,请刷新后重试")
return
end
local get_ok, get_err = skynet.call(my_scene, "lua", "auction_get_yb_after_do", my_obj_id, item_name, yuanbao)
if not get_ok then
ma_func:notify_tips(get_err or "领取售出元宝失败,请稍后重试")
return
end
remove_auction_box_merchadise(self.type, self.index)
...
end
文件:/home/ubuntu/Game2/services/ybexchange/ybexchange_core.lua
local function build_auction_query(merchadise, status)
if not merchadise or merchadise.seller_guid == nil or merchadise.item == nil then
return nil, "寄售信息已失效,请刷新后重试"
end
...
return query_tbl
end
function ybexchange_core:get_sold_out_yuanbao(request)
local coll_name = "ybmarket"
local selector = {["_id"] = false}
local query_tbl, err_msg = build_auction_query(request, "buyed")
if not query_tbl then
return nil, nil, err_msg
end
local merchadise = skynet.call(".db", "lua", "findOne", {
collection = coll_name,
query = query_tbl,
selector = selector
})
if not merchadise then
return nil, nil, "寄售信息已失效,请刷新后重试"
end
local sql = { collection = coll_name, selector = query_tbl, single = true}
skynet.call(".db", "lua", "delete", sql)
local price = tonumber(merchadise.price) or 0
if price < 0 then
price = 0
end
return merchadise.item_name or "商品", price
end
文件:/home/ubuntu/Game2/services/scene/scenecore.lua
function scenecore:auction_get_yb_after_do(who, item_name, yuanbao)
local obj_me = self:get_obj_by_id(who)
if not obj_me then
return false, "角色不存在"
end
yuanbao = tonumber(yuanbao) or 0
if yuanbao < 0 then
yuanbao = 0
end
item_name = item_name or "商品"
yuanbao = ybmarket_helper.calc_seller_income(yuanbao)
...
obj_me:set_yuanbao(obj_me:get_yuanbao() + yuanbao, "元宝交易市场-出售商品")
return true
end
6.3 取回 / 过期取回
文件:/home/ubuntu/Game2/services/msgagent.lua
CGAuctionTakeBack() 和 CGAuctionExpireBack() 改成:
- 先判
auction_box_list
- 再取缓存项
- DB 查不到时给提示,不崩
- 成功或明确失效后,同步删本地缓存
文件:/home/ubuntu/Game2/services/ybexchange/ybexchange_core.lua
function ybexchange_core:take_back(merchadise)
local coll_name = "ybmarket"
local selector = {["_id"] = false}
local query_tbl, err_msg = build_auction_query(merchadise, "on_sale")
if not query_tbl then
return nil, err_msg
end
merchadise = skynet.call(".db", "lua", "findOne", {
collection = coll_name,
query = query_tbl,
selector = selector
})
if not merchadise then
return nil, "寄售信息已失效,请刷新后重试"
end
...
end
function ybexchange_core:expire_back(merchadise)
local coll_name = "ybmarket"
local selector = {["_id"] = false}
local query_tbl, err_msg = build_auction_query(merchadise, "off")
if not query_tbl then
return nil, err_msg
end
merchadise = skynet.call(".db", "lua", "findOne", {
collection = coll_name,
query = query_tbl,
selector = selector
})
if not merchadise then
return nil, "寄售信息已失效,请刷新后重试"
end
...
end
文件:/home/ubuntu/Game2/services/scene/scenecore.lua
function scenecore:auction_merchadise_take_back_before_check(who, merchadise)
local obj_me = self:get_obj_by_id(who)
if not obj_me then
return false, "角色不存在"
end
if not merchadise or not merchadise.item then
return false, "寄售信息已失效,请刷新后重试"
end
...
end
7. 当前结果
- 上架价格、改价价格统一从配置读取
- 成交到账税率从配置读取
- 上架/改价手续费从配置读取
- 改价先校验、再扣费、失败回退
- 领取售出元宝、取回、过期取回都补了缓存失效和空值防御
- 客户端不改,服务端为准
实测重点:
- 上架价格
1、200001、正常价格
- 改价改成
0、负数、超上限、正常价格
- 改价失败后,交子/金币是否正确回退
- 降价后不返还手续费是否符合预期
- 售出后领取元宝,连续点两次是否只提示刷新,不再报错
- 取回、过期取回连续点两次是否只提示刷新,不再报错