事件回调参数
使用 samp.events.on 订阅。每个回调接收一个 event table。
公共 Envelope
每个事件都包含:
| 字段 | 类型 | 说明 |
|---|---|---|
name | string | 精确事件名。 |
sequence | integer | 运行时内单调递增的派发序号;同一次派发的所有订阅者看到相同值。 |
timestamp | integer | 单调时钟毫秒数,不是系统日期时间。 |
sessionId | integer | 事件所属会话。 |
playerGeneration | integer | 事件对应的本地玩家世代。 |
payload table 只应在当前回调中使用;任务需要延后处理时复制其中的基础值。 未标记“可写”的字段即使被修改,也不会影响宿主行为。
生命周期、帧与 UI
| 事件 | 附加字段 | 说明 |
|---|---|---|
plugin.loaded | 无 | 入口文件加载后派发;必须在入口求值期间订阅。 |
plugin.unloading | 无 | 释放订阅、任务和效果前派发。 |
session.started | 无 | 新运行会话开始。 |
session.ended | 无 | 当前会话结束。 |
game.ready | 无 | 游戏服务就绪。 |
server.connected | 无 | 多人游戏连接完成。 |
server.disconnected | 无 | 连接结束。 |
player.spawned | 无 | 应在这里重新取得玩家及相关资源。 |
player.died | 无 | 旧玩家世代资源应视为失效。 |
game.frame | deltaSeconds: number | 每帧托管回调,工作必须有界。 |
draw.hud | deltaSeconds、screenWidth、screenHeight: number | 唯一允许调用 samp.draw 的阶段。 |
ui.menu_opened | 无 | 本插件菜单打开;需要 ui.menu。 |
ui.menu_closed | 无 | 本插件菜单关闭;需要 ui.menu。 |
ui.control_changed | pluginId、pageId、controlId、valueType、value | switch 为 boolean;slider/number_input 为归一化 number;选择类控件和 list 为 string;button/confirm_button 为 action/click;group 为 action/toggle。应按页面和控件 ID 过滤。 |
ui.control_changed 只由可交互控件产生。section、text、divider 和 progress 是仅展示控件;multi_choice 回传被切换选项的 value, text_input 和 color_picker 在用户点击“应用”后才回传,list 回传被点击条目的 value。
本地玩家事件
| 事件 | 权限 | Payload |
|---|---|---|
player.health_changed | game.player.read | previousHealth: number、health: number。 |
player.vehicle_entered | game.vehicle.read | vehicleId: integer、passenger: boolean。 |
player.vehicle_left | game.vehicle.read | vehicleId: integer、passenger: boolean。 |
player.interior_changed | game.state.read | previousInterior: integer、interior: integer。 |
player.weapon_changed | game.player.read | 之前和当前武器 ID。 |
player.aiming_changed | game.player.read | 之前和当前瞄准状态。 |
player.motion_changed | game.player.read | previousActivity、activity、previousMoveState、moveState、onGround、inAir。 |
player.vehicle_collision | game.vehicle.read | vehicleId、otherType(vehicle、player 或 world)、可选 otherId、impact、speed、position。 |
player.skin_changed | game.player.read | previousSkin、skin。 |
player.animation_changed | game.player.read | previousAnimation、animation。 |
player.task_changed | game.player.read | previousCategory、category、previousType、previousName、type、name。 |
world.time_changed | game.state.read | previousHour、previousMinute、hour、minute。 |
world.weather_changed | game.state.read | previousWeather、previousHoldTime、weather、holdTime。 |
vehicle.health_changed | game.vehicle.read | 载具 ID 和之前/当前生命值。 |
vehicle.state_changed | game.vehicle.read | vehicleId、previousModel、model、可选 previousHeading/heading,以及引擎、车灯、警报状态的前后布尔值。 |
player.damage_before
需要 game.player.write:
| 字段 | 类型 | 可变性 |
|---|---|---|
damage | number | 可写,有限 0..100000;写入 0 可阻止伤害。 |
weaponType | integer | 只读输入。 |
bodyPart | integer | 只读输入。 |
sourceType | "player"、"actor" 或 "entity" | 只读输入。 |
sourcePlayerId | integer | 仅来源是已知玩家时存在。 |
sourceActorId | integer | 仅来源是已知 Actor 时存在。 |
回调按优先级执行,后续回调能看到之前已接受的 damage。无效修改会被忽略, 该回调不能 yield。
派发与生命周期规则
游戏、网络和 Android UI 线程只会把不可变快照写入容量为 256 的有界队列, 下一游戏主线程帧再派发;网络观测最多占用 96 项,普通通知最多占用 224 项, 以便为生命周期事件保留空间。队列满时丢弃新的通知,网络线程不会等待 Lua。
玩家可用状态和 generation 使用独立的可靠状态同步,因此不会因通知队列满而 丢失。状态变化每帧最多采样一次,在生命周期事件之后、game.frame 和 draw.hud 之前派发。直接切换载具时先派发 player.vehicle_left,再派发 player.vehicle_entered。出生、重连或运行中启用插件后的首次采样只建立基线, 不会补发历史变化;即使事件在 generation 改变前入队,也必须重新获取旧 Handle。
聊天事件
| 事件 | 权限 | Payload |
|---|---|---|
chat.message_received | chat.read | playerId: integer、playerName: string、message: string、localPlayer: boolean。 |
chat.server_message_received | chat.read | message: string、color: integer(ARGB)。 |
chat.bubble_received | chat.read | playerId: integer、message: string、color: integer、drawDistance: number、durationMs: integer。 |
chat.message_sending
需要 chat.intercept。message: string 与 cancelled: boolean 可写。 替换文本必须是有效 UTF-8、非空、最多 4,096 字节,不含 NUL/CR/LF,且不能 以 / 开头。
command.executing
需要 command.intercept。command: string 与 cancelled: boolean 可写。 替换值同样最多 4,096 字节且不能包含换行,必须以 / 开头,并至少还有一个 字符。
两者的取消都是粘性的:一旦设为 true,后续回调不能恢复为 false。可变拦截 回调不能 yield。
检查点事件
checkpoint.entered 与 checkpoint.left 需要 game.state.read。
| 字段 | 类型 | 说明 |
|---|---|---|
kind | "normal" 或 "race" | 检查点类型。 |
position | Vector3 | 坐标。 |
size | Vector3 | 方盒形检查点时存在。 |
radius | number | 半径形检查点时存在。 |
raceType | integer | 与 radius 一同存在。 |
服务器实体事件
entity.streamed_in 与 entity.streamed_out 需要 game.entity.read:
| 字段 | 类型 |
|---|---|
entityType | player、vehicle、object、actor、pickup 或 text_label |
entityId | integer |
streamGeneration | 正 integer |
streamed_in 时可将三个字段传给 samp.entity.get;streamed_out 后对应旧 Handle 已失效。
input.touch、camera.mode_changed 与网络事件
input.touch 需要 ui.input,在触摸传递给游戏前同步派发,字段为 action(down、move、up、cancel)、pointerId、屏幕像素坐标 x/y、屏幕尺寸 width/height、限制在 0..1 的 normalizedX/normalizedY 和可写的 cancelled。将 cancelled 设为 true(或回调返回 false)会消费手势,同一 pointer 序列后续事件保持消费。 camera.mode_changed 需要 game.state.read,提供 previousMode 和 mode。
network.packet_received、network.rpc_received、network.packet_sending 和 network.rpc_sending 需要 network.inspect,发送前的两个对应事件需要 network.intercept。它们提供 packet/RPC ID、来源、字节/位长度、最多 4096 字节的 payload 前缀和 truncated;只有发送前事件允许修改粘性的 cancelled。观测是异步的,拦截在运行时无法安全同步执行时会放行。
pickup.collected
需要 game.entity.read,提供 pickupId、model、type 和 position,是 只读通知,不提供可变的 Pickup Handle。
Dialog 事件
dialog.shown
需要 dialog.read:
| 字段 | 类型 | 说明 |
|---|---|---|
dialogId | integer | 0..32767。 |
styleId | integer | 数字样式 0..5。 |
style | string | message、input、list、password、tablist 或 tablist_headers。 |
title | string | 标题。 |
message | string | 正文或列表数据。 |
primaryButton | string | 主按钮文字。 |
secondaryButton | string | 次按钮文字,可能为空。 |
所有字符串均为 UTF-8;title 和每个按钮最长 1,024 字节,message 最长 16 KiB。
dialog.responding
需要 dialog.intercept。accepted: boolean、listItem: integer (-1..65534)、input: string(有效 UTF-8、最多 4,096 字节、不含 NUL/CR/LF)以及 cancelled: boolean 可写;dialogId 只读。取消是粘性的, 无效替换会被忽略,回调不能 yield。
TextDraw 事件
TextDraw 身份由 textdrawId(0..3071)和正整数 textdrawGeneration 共同组成。
| 事件 | 权限 | 附加 Payload |
|---|---|---|
textdraw.shown | textdraw.read | 身份、styleId: integer、text: string、selectable: boolean、x: number、y: number。 |
textdraw.hidden | textdraw.read | 身份。 |
textdraw.text_changed | textdraw.read | 身份、text: string。 |
textdraw.clicking | textdraw.intercept | 身份、可写 cancelled: boolean。 |
事件中的 text 最多 4,096 字节。点击取消是粘性的,拦截回调不能 yield。