竞拍系统
05/161 浏览综合
现在我已经完全了解了整个竞拍链路。来梳理改造方案:
当前问题:ServerAuction 是"即时成交"模式——出价后立即扣款、直接转移所有权。用户希望改为"出价竞拍"模式:出价扣款,记录最高出价,显示当前最高出价者和金额。
改造计划:
服务端:记录每栋建筑的最高出价(内存 + 广播),出价时扣款,如果被超过则退回前一个最高出价者的钱,超过才成交转所有权
广播:AUCTION_STATUS 广播当前最高出价信息(userId + amount + nickname 用 userId 代替,客户端用 BuildingOwnerHelper 去查昵称)
客户端:三个弹窗显示当前最高出价信息
竞拍系统的完整改造已全部完成并构建通过。以下是本轮实现的内容总结:
服务端 (ServerAuction.lua) — 之前已完成:
竞价模式:玩家出价时立即扣除现金,记录到 auctionRecords
超价退款:有人出更高价时,自动退还前一位最高出价者的现金
广播机制:每次竞价变动后向所有在线玩家广播最高出价信息
客户端三个弹窗 (BankModal / TavernModal / Marketplace) — 本轮完成:
添加了 OnBidResult 回调:显示竞拍操作结果(成功/失败消息)
添加了 OnAuctionStatus 回调:实时更新"最高出价: X 元 (玩家昵称)"
通过 BuildingOwnerHelper.FetchNickname 异步解析玩家 ID 为昵称
main.lua — 本轮完成:
OnBidResult 和 OnAuctionStatus 回调统一转发到三个弹窗
竞拍广播同时触发地图重绘(gameMapData.dirty = true)
可以进入游戏测试竞拍功能了。打开任意无主建筑弹窗,输入出价金额后点击竞拍,应该能看到现金被扣除,并显示当前最高出价者信息。
24 小时竞拍超时机制 - 改动汇总
服务端 (ServerAuction.lua)
竞拍不再即时转移所有权,改为挂起模式
每次出价记录 lastBidTime 和 deadline(= 出价时间 + 24h)
新增 ServerAuction.Update(dt) —— 每 30 秒扫描一次到期竞拍
到期后调用 finalizeAuction() 自动将所有权转给最高出价者,持久化到云端并广播
服务端入口 (Server.lua)
新增 SubscribeToEvent("Update", "HandleServerUpdate"),驱动竞拍定时检查
客户端三个弹窗 (BankModal / TavernModal / Marketplace)
updateBidStatus() 新增 deadline 参数
收到竞拍广播时,根据 deadline - os.time() 计算剩余时间,显示格式:最高出价: 500 元 (玩家昵称) | 剩余 23:45:30
竞拍结束后显示 | 已截止
数据流
出价 → 服务端扣款 → auctionRecords[deadline] → 广播 deadline 给所有客户端
↓
客户端显示倒计时
↓
24h 无人加价 → finalizeAuction → 转移所有权
确认问题根源:
ServerAuction 读写 player_stats 的 stats.asset(该字段 = cash + deposit,且仅在银行操作后才同步)
ServerBank 真实现金存在 bank_account 的 acct.cash(唯一信源)
玩家如果没执行过银行操作,player_stats.asset 可能为 0,导致竞拍提示"当前 0"
现在修复 ServerAuction.lua,改为读写 bank_account.cash,并在扣款/退款后同步 player_stats。
修复内容总结:
问题根因:竞拍系统(ServerAuction)读写的是 player_stats.asset(派生字段,= cash + deposit,仅在银行操作后才同步),而玩家真实现金存储在 bank_account.cash。新玩家或未执行过银行操作的玩家,player_stats.asset 为 0,导致竞拍报"现金不足(当前 0)"。
修复内容(ServerAuction.lua):
HandleBidBuilding 扣款:从 serverCloud:Get(userId, "stats") → 改为 serverCloud:Get(userId, S.BANK_ACCOUNT_KEY),读取 acct.cash 判断余额、扣款后写回 bank_account
refundPlayer 退款:同样改为读写 bank_account.cash
新增 syncStatsAfterAuction:扣款/退款后同步 player_stats.asset = cash + deposit,并推送 STATS_LOADED 给客户端,保持 UI 显示与实际数据一致
现在竞拍系统与钱庄共用同一数据源 bank_account,信道已打通。


