私聊是玩家社交的私信箱:交易的对口、好友的寒暄、行会的动员暗号全走私聊。私聊协议的要点是点对点的寻址、离线的转投与骚扰的防线——一句话送不到人或送出骚扰都是事故。
---私聊的发送:在线直投与离线转投
function Chat.private(actor, toName, text)
local player = class(actor)
if not player then return false end
local target = getplayerbyname(toName)
if not target then return false end
-- 黑名单的拦截
if Friend.blacklisted(toName, actor) then
sendmsg(actor, 1, "消息无法送达")
return false
end
-- 频控:每分钟最多 20 条
if not Chat.freqOk(actor, 20, 60) then
sendmsg(actor, 1, "发送过于频繁")
return false
end
sendmsg(target, 1, "[私聊] " .. actor .. ":" .. text)
Chat.storeOffline(actor, toName, text)
return true
end
私聊的投递先过两道闸:黑名单的拦截让拉黑者安静、频控的 20 条每分钟掐住刷屏的手。在线的目标直投送达,收发双方的记录同步存储——私聊的留痕是举报取证的原料,聊天记录的保留 30 天。送达的回执给发送方确定性:消息进了对方的屏幕还是转了离线,发送的界面有状态可查。
---离线的转投:消息转邮件到达
setontimerex(99, 60)
function Chat.offlineFlush()
for uid, box in pairs(Chat.offlineBox) do
if #box > 0 and Online.isOnline(uid) then
sendmsg(uid, 1, "有 " .. #box ..
" 条离线私聊,点击查看")
-- 上线后的首屏拉取离线消息
Chat.deliverPending(uid, box)
Chat.offlineBox[uid] = nil
elseif #box > 50 then
-- 离线积压超 50 条转邮件摘要
sendmail(uid, 8010, "离线消息摘要",
table.concat(box, "\n"), "")
Chat.offlineBox[uid] = nil
end
end
end
离线的转投分两档:玩家上线后直接补投的待领箱、积压超 50 条转邮件摘要的兜底——离线的私聊不丢失也不无限积压。转投的时机按收件方的状态驱动:上线即达的体验与邮件的兜底并行。私聊的过滤与频道的同源:敏感词的筛查在私聊同样生效,引流的诈骗话术在点对点的通道同样被拦——私聊不是法外之地。私聊的已读回执做轻量的版本:送达的状态有、已读不追踪,隐私的边界比社交的确认更重要。
私聊的送达率与延迟监控,直投的延迟超 500 毫秒即网络或网关的排查;离线积压的分布统计,积压的存量反映转投机制的健康的程度。
黑名单的拦截曾经不提示发送方,发送方以为送达了反复重发,模糊化的失败提示让双方都得体。离线箱的键曾经用玩家名字,改名后离线消息找不到主人,键的统一 userId。转邮件的摘要曾经不带发送者,收到的邮件像匿名信,摘要的格式带来源。
私聊的入口与好友、行会列表联动,点名字即私聊的动线最短。陌生人私聊的开关给玩家,骚扰的拒绝权在接收者手里。私聊的记录查询进客服的取证工具,交易纠纷的调证有时效保障。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
实战应用:用在哪里 战士克法师、法师克道士、道士克战士——三角的克制是传奇职业平衡的骨架。克制框架的要点是相性的数值化、克制…
实战应用:用在哪里 挂机 24 小时的收益与玩 2 小时一样多吗?疲劳值系统回答产出节奏的问题:每日的疲劳额度框定有效收益的…
实战应用:用在哪里 GM 发出去的每一件补偿、踢掉的每一个号都要能查:审计的数据躺在日志里不算难,检索的效率决定追责与复盘的…
实战应用:用在哪里 师徒链的层级遍历、行会职位的树状结构、嵌套菜单的展开——递归的写法优雅但栈深是隐形的雷。递归改写把深层的…
实战应用:用在哪里 找回密码是账号安全的压轴救援通道,也是社工攻击的突破口:骗过客服就能偷走别人的账号。找回的流程设计在「帮…
实战应用:用在哪里 行会基金是行会的公共金库:沙巴克的税收、成员的捐献、活动的奖金全进这一个池子,基金的每一笔进出都要对得上…