> For the complete documentation index, see [llms.txt](https://ak-scripts.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ak-scripts.gitbook.io/docs/yi-lai/markdown/gong-neng-mo-kuai-dao-chu/leng-que-jie-liu-cooldown.md).

# 冷却节流（Cooldown）

## ⏱️ Cooldown/Throttle（冷却节流）模块导出文档

### 📋 概述

Cooldown/Throttle 模块提供了两种操作频率限制机制：

* **Cooldown（冷却时间）**：在指定时间内阻止重复执行某个操作
* **Throttle（节流）**：在指定时间窗口内限制操作的最大执行次数

### 🚀 导出方式

#### 服务端

**方式 1：获取模块对象（推荐）⭐**

```lua
local Cooldown = exports['ak-lib']:CooldownModule()
```

**方式 2：单独导出函数**

```lua
exports['ak-lib']:SetCooldown(identifier, 'heal', 5000)
```

#### 客户端

**方式 1：获取模块对象（推荐）⭐**

```lua
local Cooldown = exports['ak-lib']:Cooldown()
```

**方式 2：单独导出函数**

```lua
exports['ak-lib']:SetCooldown('heal', 5000)
```

### 📖 可用导出

#### 服务端

**Cooldown（冷却）相关**

| 导出                                           | 说明           | 参数                                                                        | 返回值             |
| -------------------------------------------- | ------------ | ------------------------------------------------------------------------- | --------------- |
| `CooldownModule()`                           | 返回模块对象       | -                                                                         | `AKCooldown` 对象 |
| `SetCooldown(identifier, key, duration)`     | 设置冷却时间       | `identifier` (string), `key` (string), `duration` (number, 可选, 默认 1000ms) | boolean         |
| `HasCooldown(identifier, key)`               | 检查是否处于冷却中    | `identifier`, `key`                                                       | boolean         |
| `GetCooldownRemaining(identifier, key)`      | 获取剩余冷却时间     | `identifier`, `key`                                                       | number (毫秒)     |
| `ClearCooldown(identifier, key)`             | 清除指定冷却       | `identifier`, `key`                                                       | boolean         |
| `ClearAllCooldowns(identifier)`              | 清除所有冷却       | `identifier`                                                              | boolean         |
| `CheckCooldown(identifier, key, duration)` ⭐ | 检查并设置冷却（语义糖） | `identifier`, `key`, `duration` (可选, 默认 1000ms)                           | boolean         |

**Throttle（节流）相关**

| 导出                                               | 说明                | 参数                                                                             | 返回值         |
| ------------------------------------------------ | ----------------- | ------------------------------------------------------------------------------ | ----------- |
| `SetThrottle(identifier, key, maxCount, window)` | 设置节流规则            | `identifier`, `key`, `maxCount` (number, 默认 10), `window` (number, 默认 60000ms) | boolean     |
| `CanThrottle(identifier, key)`                   | 检查是否可以执行（自动记录）    | `identifier`, `key`                                                            | boolean     |
| `GetThrottleCount(identifier, key)`              | 获取当前时间窗口内的执行次数    | `identifier`, `key`                                                            | number      |
| `GetThrottleRemaining(identifier, key)`          | 获取距离下一次可执行还需等待的时间 | `identifier`, `key`                                                            | number (毫秒) |
| `ClearThrottle(identifier, key)`                 | 清除指定节流规则          | `identifier`, `key`                                                            | boolean     |
| `ClearAllThrottles(identifier)`                  | 清除所有节流规则          | `identifier`                                                                   | boolean     |

**Debug 相关**

| 导出                        | 说明                | 参数 | 返回值         |
| ------------------------- | ----------------- | -- | ----------- |
| `GetCooldownDebugStats()` | 获取调试统计（需启用 Debug） | -  | table / nil |

#### 客户端

（同上，但所有方法都不需要 `identifier` 参数）

| 导出                                   | 说明        | 参数                          | 返回值             |
| ------------------------------------ | --------- | --------------------------- | --------------- |
| `Cooldown()`                         | 返回模块对象    | -                           | `AKCooldown` 对象 |
| `SetCooldown(key, duration)`         | 设置冷却时间    | `key`, `duration`           | boolean         |
| `HasCooldown(key)`                   | 检查是否处于冷却中 | `key`                       | boolean         |
| `GetCooldownRemaining(key)`          | 获取剩余冷却时间  | `key`                       | number          |
| `ClearCooldown(key)`                 | 清除指定冷却    | `key`                       | boolean         |
| `ClearAllCooldowns()`                | 清除所有冷却    | -                           | boolean         |
| `CheckCooldown(key, duration)` ⭐     | 检查并设置冷却   | `key`, `duration`           | boolean         |
| `SetThrottle(key, maxCount, window)` | 设置节流规则    | `key`, `maxCount`, `window` | boolean         |
| `CanThrottle(key)`                   | 检查是否可以执行  | `key`                       | boolean         |
| `GetThrottleCount(key)`              | 获取执行次数    | `key`                       | number          |
| `GetThrottleRemaining(key)`          | 获取剩余等待时间  | `key`                       | number          |
| `ClearThrottle(key)`                 | 清除节流规则    | `key`                       | boolean         |
| `ClearAllThrottles()`                | 清除所有节流规则  | -                           | boolean         |

### 💡 使用示例

#### Cooldown（冷却）使用示例

**服务端**

```lua
local Cooldown = exports['ak-lib']:CooldownModule()
local FW = exports['ak-lib']:Framework()

RegisterCommand('heal', function(source, args)
    local identifier = FW.GetIdentifier(source)
    
    -- 方式 1：使用 CheckCooldown（推荐）⭐
    if not Cooldown.CheckCooldown(identifier, 'heal', 5000) then
        local remaining = Cooldown.GetCooldownRemaining(identifier, 'heal')
        TriggerClientEvent('ak-lib:Notify', source, {
            type = 'error',
            message = string.format('请等待 %d 秒后再使用', math.ceil(remaining / 1000))
        })
        return
    end
    
    -- 执行治疗逻辑（已自动设置冷却）
    TriggerClientEvent('ak-lib:Notify', source, {
        type = 'success',
        message = '已治疗'
    })
end, false)

-- 方式 2：分步检查（需要更细粒度控制时使用）
RegisterCommand('heal2', function(source, args)
    local identifier = FW.GetIdentifier(source)
    
    if Cooldown.HasCooldown(identifier, 'heal') then
        local remaining = Cooldown.GetCooldownRemaining(identifier, 'heal')
        TriggerClientEvent('ak-lib:Notify', source, {
            type = 'error',
            message = string.format('请等待 %d 秒', math.ceil(remaining / 1000))
        })
        return
    end
    
    -- 执行治疗逻辑
    Cooldown.SetCooldown(identifier, 'heal', 5000)
    TriggerClientEvent('ak-lib:Notify', source, {
        type = 'success',
        message = '已治疗'
    })
end, false)
```

**客户端**

```lua
local Cooldown = exports['ak-lib']:Cooldown()

RegisterCommand('lock', function()
    -- 推荐：使用 CheckCooldown
    if not Cooldown.CheckCooldown('lock', 2000) then
        local remaining = Cooldown.GetCooldownRemaining('lock')
        exports['ak-lib']:Notify({
            type = 'error',
            message = string.format('请等待 %d 秒', math.ceil(remaining / 1000))
        })
        return
    end
    
    -- 执行锁定逻辑（已自动设置冷却）
end, false)
```

#### Throttle（节流）使用示例

**服务端**

```lua
local Cooldown = exports['ak-lib']:CooldownModule()
local FW = exports['ak-lib']:Framework()

RegisterCommand('report', function(source, args)
    local identifier = FW.GetIdentifier(source)
    
    -- 检查节流（每分钟最多 3 次）
    if not Cooldown.CanThrottle(identifier, 'report') then
        local remaining = Cooldown.GetThrottleRemaining(identifier, 'report')
        TriggerClientEvent('ak-lib:Notify', source, {
            type = 'error',
            message = string.format('操作过于频繁，请等待 %d 秒', math.ceil(remaining / 1000))
        })
        return
    end
    
    -- 执行举报逻辑（已自动记录本次调用）
    local message = table.concat(args, ' ')
    print(string.format('[举报] 玩家 %d: %s', source, message))
    
    TriggerClientEvent('ak-lib:Notify', source, {
        type = 'success',
        message = '举报已提交'
    })
end, false)

-- 在资源启动时设置节流规则（可选）
AddEventHandler('onResourceStart', function(resourceName)
    if GetCurrentResourceName() ~= resourceName then return end
    
    -- 注意：实际使用时应该在玩家加入时设置，这里仅作示例
    -- 通常在使用时才动态设置，或者通过其他机制管理
end)
```

**客户端**

```lua
local Cooldown = exports['ak-lib']:Cooldown()

-- 设置交互节流：每 500ms 最多 1 次
Cooldown.SetThrottle('interact', 1, 500)

RegisterCommand('+interact', function()
    if not Cooldown.CanThrottle('interact') then
        return  -- 静默忽略，避免刷屏
    end
    
    -- 执行交互逻辑
end, false)
```

#### 完整示例：防止刷屏和滥用

**服务端**

```lua
local Cooldown = exports['ak-lib']:CooldownModule()
local FW = exports['ak-lib']:Framework()

-- 举报系统：使用 Throttle（每分钟最多 3 次）
RegisterCommand('report', function(source, args)
    local identifier = FW.GetIdentifier(source)
    
    if not Cooldown.CanThrottle(identifier, 'report') then
        local remaining = Cooldown.GetThrottleRemaining(identifier, 'report')
        TriggerClientEvent('ak-lib:Notify', source, {
            type = 'error',
            message = string.format('举报过于频繁，请等待 %d 秒', math.ceil(remaining / 1000))
        })
        return
    end
    
    local message = table.concat(args, ' ')
    if not message or message == '' then
        TriggerClientEvent('ak-lib:Notify', source, {
            type = 'error',
            message = '请输入举报内容'
        })
        return
    end
    
    -- 处理举报逻辑
    print(string.format('[举报] 玩家 %d: %s', source, message))
    
    TriggerClientEvent('ak-lib:Notify', source, {
        type = 'success',
        message = '举报已提交，管理员会尽快处理'
    })
end, false)

-- 治疗系统：使用 Cooldown（10 秒冷却）
RegisterCommand('heal', function(source, args)
    local identifier = FW.GetIdentifier(source)
    
    if not Cooldown.CheckCooldown(identifier, 'heal', 10000) then
        local remaining = Cooldown.GetCooldownRemaining(identifier, 'heal')
        TriggerClientEvent('ak-lib:Notify', source, {
            type = 'error',
            message = string.format('治疗冷却中，剩余 %d 秒', math.ceil(remaining / 1000))
        })
        return
    end
    
    -- 执行治疗
    TriggerClientEvent('ak-lib:Notify', source, {
        type = 'success',
        message = '已治疗'
    })
end, false)
```

**客户端**

```lua
local Cooldown = exports['ak-lib']:Cooldown()

-- 限制交互频率
Cooldown.SetThrottle('interact', 1, 500)  -- 每 500ms 最多 1 次

RegisterCommand('+interact', function()
    if not Cooldown.CanThrottle('interact') then
        return
    end
    
    -- 执行交互逻辑
end, false)

-- 武器切换冷却：1 秒
RegisterCommand('switchweapon', function()
    if Cooldown.HasCooldown('weapon_switch') then
        return
    end
    
    -- 切换武器逻辑
    Cooldown.SetCooldown('weapon_switch', 1000)
end, false)
```

#### Debug 统计（服务端）

```lua
local Cooldown = exports['ak-lib']:CooldownModule()

-- 仅在 Config.Debug.Enabled = true 时有效
local stats = Cooldown.GetDebugStats()
if stats then
    print(string.format('活跃冷却: %d, 活跃节流: %d', 
        stats.activeCooldowns, stats.activeThrottles))
    
    -- 查看节流命中统计
    for key, hits in pairs(stats.throttleHits) do
        print(string.format('%s: 命中 %d 次', key, hits))
    end
end
```

### 📝 API 详细说明

#### CheckCooldown（语义糖接口）⭐

`CheckCooldown` 是一个便捷接口，将常用的"检查冷却 → 设置冷却"模式合并为一行代码。

**对比：**

```lua
-- ❌ 旧方式（两行代码）
if Cooldown.HasCooldown(identifier, 'heal') then
    return
end
Cooldown.SetCooldown(identifier, 'heal', 5000)

-- ✅ 新方式（一行代码）
if not Cooldown.CheckCooldown(identifier, 'heal', 5000) then
    return
end
```

**返回值：**

* `true`：已设置冷却并允许执行
* `false`：仍在冷却中，不允许执行

**推荐使用场景：**

* 简单的冷却检查场景
* 需要立即返回的场景
* 代码简化需求

**仍推荐使用 `HasCooldown` + `SetCooldown` 的场景：**

* 需要在检查和设置之间执行其他逻辑
* 需要更细粒度的控制

#### CanThrottle（自动记录）

`CanThrottle` 会自动记录本次调用时间戳：

* 返回 `true`：已记录并允许执行
* 返回 `false`：已达到限制，不允许执行

**注意：** 如果返回 `true`，表示已记录本次调用，无需再次调用其他函数。

### ⚠️ 注意事项

1. **服务端 identifier**：服务端 API 需要 `identifier` 参数来区分不同玩家，建议使用 `FW.GetIdentifier(source)` 获取。
2. **自动清理**：模块会自动清理过期的冷却和节流数据，无需手动维护。
3. **性能考虑**：Throttle 会维护时间戳数组，对于高频操作建议合理设置 `maxCount` 和 `window`。
4. **玩家退出清理**：服务端的 Cooldown 和 Throttle 数据会一直存在，建议在玩家永久退出时清理（可选）。
5. **推荐使用 CheckCooldown**：对于简单的冷却场景，推荐使用 `CheckCooldown` 语义糖接口，代码更简洁。
6. **Cooldown vs Throttle**：
   * **Cooldown**：适用于"使用后等待固定时间"的场景（如治疗、技能冷却）
   * **Throttle**：适用于"在 X 时间内最多执行 Y 次"的场景（如消息发送、API 调用）
7. **友好提示**：当限制触发时，提供清晰的剩余时间提示，提升用户体验。

### 🔗 相关文档

* 冷却节流说明
* Framework 模块导出文档


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ak-scripts.gitbook.io/docs/yi-lai/markdown/gong-neng-mo-kuai-dao-chu/leng-que-jie-liu-cooldown.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
