CHUAN2 DEV ENGINE
996 正版授权研发中心 · 360 授权合作教学中心 · 抖音传奇直播合作授权 · 快手推广运营商授权
OFFICIAL LICENSED ACADEMY 查验官方授权证书 →
// 威海旷世互娱教学基地 · 技术文章
入门夯实996引擎幂等重复触发

【入门夯实】触发重复:同一帧触发的幂等习惯

2026-09-25 00:45 作者:996 技术组 0 阅读 996引擎Lua教程传奇脚本入门夯实996引擎Lua幂等重复触发

学员常见误区

攻城报名按钮被快速连点,客户端一帧内投递了两次触发请求:处理函数没有任何防重,两次都通过校验、两次都扣报名费、名单里出现两条同名记录——玩家多花一倍报名费还以为赚了两个名额。学员以为"按钮点了两次是客户端的事",服务端不设防就是资损。错误场景:

lua
local function onSignup(actor)
    actor = getplayerbyname(actor)
    takeitem(actor, "祖玛头像", 1, 0, "攻城报名")
    setplayvar(actor, "HUMAN", "SiegeJoined", 1, 1)
    sendmsg(actor, 1, "报名成功!")
end

一帧两次触发,扣两次头像、发两次成功提示。

正确姿势

处理入口配幂等标记:用毫秒级时间戳做窗口去重,窗口内的重复触发直接丢弃。规范写法。示例代码如下:

lua
local function onSignup(actor)
    actor = getplayerbyname(actor)
    local now = os.clock() * 1000
    local last = tonumber(getplayvar(actor, "HUMAN", "SignupTick")) or 0
    if now - last < 200 then
        return
    end
    setplayvar(actor, "HUMAN", "SignupTick", math.floor(now), 0)
    if not takeitem(actor, "祖玛头像", 1, 0, "攻城报名") then
        sendmsg(actor, 1, "背包中没有祖玛头像。")
        return
    end
    setplayvar(actor, "HUMAN", "SiegeJoined", 1, 1)
    sendmsg(actor, 1, "报名成功!")
end

200 毫秒窗口内的第二次触发被静默丢弃;先扣材料后置状态,扣材料失败即终止,状态不会出现半拉子。示例代码如下:

lua
local function alreadyJoined(actor)
    return getplayvar(actor, "HUMAN", "SiegeJoined") == 1
end

幂等窗口之外再加一层业务判重(已报名直接返回),两层防线各管一种重复。

引擎验证

三步验证:模拟一帧内两次调用,第二次被窗口拦截只扣一次材料;把窗口调大到 5000 毫秒复测,正常的两次相隔一秒的报名也被误拦——体会窗口大小的取舍;已报名的玩家再次触发,被业务判重直接返回。

举一反三

不同操作的幂等键要独立:报名、捐献、兑换各用各的标记变量,共用一个时间戳窗口会互相误伤。示例代码如下:

lua
local function guard(name, key, windowMs)
    local now = os.clock() * 1000
    local last = tonumber(getplayvar(name, "HUMAN", key)) or 0
    if now - last < windowMs then
        return false
    end
    setplayvar(name, "HUMAN", key, math.floor(now), 0)
    return true
end

guard 把窗口去重抽成公共函数,key 区分操作,三个入口三把锁。

作者履历与出处

本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。

← 返回文章地图返回研学路径

最新技术文章 · 实战干货

LATEST ARTICLES

全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →

高级技巧996引擎

【高级技巧】Lua常量提升:祖玛教主掉落表别在函数里重建

一、一行代码拆解:local function roll() 里写 local cfg = {500, 200, 50} —…

2026-09-26 05:50 996 技术组 · 0 阅读
进阶实战996引擎

【进阶实战】Lua数值精度上限:沙巴克国库囤金的2^53错账

一、隐蔽陷阱:国库金币累加到 2^53(约 9007199254740992)之后再加 1,数值纹丝不动——双精度浮点在该区…

2026-09-26 05:50 996 技术组 · 0 阅读
策划架构996引擎

【策划架构】Lua模块表单例:裁决之杖仓库的单一入口封装

一、线上事故:仓库存取逻辑散在 6 个脚本,各自写各自的 getsysvar 键名,某次改名漏改 2 处,300 件裁决之杖…

2026-09-26 05:50 996 技术组 · 0 阅读
策划架构996引擎

【策划架构】Lua分页切片:沙巴克战备仓库500件的翻页设计

一、抛坑提问:500 件战备装备一次下发必卡,按每页 20 件切片,边界怎么算才不出空页和重页?起点 (page-1) 20…

2026-09-26 05:50 996 技术组 · 0 阅读
进阶实战996引擎

【进阶实战】Lua error层级参数:烈火剑法报错定位到调用行

一、抛坑提问:校验失败在工具函数里 error,日志却指向工具函数那一行,排查总要翻两层。error 第二参 level 能…

2026-09-26 05:50 996 技术组 · 0 阅读
高级技巧996引擎

【高级技巧】Lua局部量200上限:裁决之杖仓库函数的寄存器分配

一、一行代码拆解:local a1, a2, a3 …… —— 单个函数最多 200 个活跃局部量,这是编译期硬限制;局部量…

2026-09-26 05:50 996 技术组 · 0 阅读