外观
实体观察
使用 ctx.actors 读取实体状态,用 actor_ref 绑定当前连接中的实体;订阅 actor.observed 可接收后续变化。
ctx.actors.observe(...) 读取当前连接已经收到的非玩家实体证据,包括身份、最新观察位置、血量、物品实体摘要、元数据、效果、装备和属性。它不发送世界查询,也不保证机器人视野外或接入前的全部实体都在结果中。查询选择器和玩家位置采样见玩家与位置。
调用与权限
text
Actors(operations: Operations)
Actors.observe(*, idempotency_key: str, deadline: str,
after: ActorCursor | None = None,
runtime_ids: list[str] | None = None) -> OperationIntentActors 与下文类型从 neomega_runtime.actors 导入;原生插件可直接使用 ctx.actors。申请 permissions.operations: ["framework.actor.observe"]。after 是 {"connection_id": str, "revision": int, "scope_revision": int};runtime_ids 可精确筛选最多 64 个十进制 runtime ID 字符串,减少无关实体占用结果容量。不要把 unique ID 传入此列表。
本方法只创建意图,必须通过 ctx.operations.submit / wait 获取回执。每次想读新证据都使用新幂等键;重用旧键取回的是原操作结果。
python
import uuid
from datetime import datetime, timedelta, timezone
async def read_actors(ctx, runtime_ids=None, after=None):
deadline = (datetime.now(timezone.utc) + timedelta(seconds=10)).isoformat()
intent = ctx.actors.observe(
idempotency_key=uuid.uuid4().hex, deadline=deadline,
runtime_ids=runtime_ids, after=after,
)
operation_id = await ctx.operations.submit(intent)
receipt = await ctx.operations.wait(operation_id, timeout=10)
if receipt["state"] != "succeeded":
raise RuntimeError(f"实体读取未确认成功:{operation_id} {receipt['state']}")
return operation_id, receipt["result"]["result"]生产业务应按操作回执保存完整意图、操作 ID 和原始回执。失败或 unknown 时保留原操作核对,不凭等待超时自动重发。
返回结构
成功结果为 ActorSnapshot 字典:
| 字段 | 类型与含义 |
|---|---|
source、connected_at | 来源与连接建立时间 |
connection_id、revision、scope_revision | 连接、观察修订号、维度等观察范围修订号;合起来构成 ActorCursor |
sampled_at、last_packet_at | 读取时刻、最后包时刻;不代表每个实体的位置都新鲜 |
dropped_through、gap、truncated | 被丢弃历史位置、缺口、结果截断标记 |
complete、complete_world_coverage | 本次证据完整性与世界覆盖标记,不能互换;不承诺全世界覆盖 |
actors、events | ActorState[] 与 ActorEvent[] |
ActorState 中所有 ID 均为十进制字符串:
| 字段 | 类型与含义 |
|---|---|
runtime_id、unique_id、entity_type | 当前观察身份及实体类型 |
spawn_position | 最近 Add 包中的三维坐标列表,不能代替缺失的当前位置 |
position | None 或 {"value": [x,y,z], "stamp": ActorStamp} |
position_error、position_error_stamp | 位置错误及对应 stamp;无 stamp 时为 None |
visible、added、removed、death | 可见状态、Add stamp、移除或明确死亡 stamp;后二者可为 None |
health | None 或 {"value": float, "min": float, "max": float, "stamp": ActorStamp} |
health_error、health_error_stamp | 血量错误及对应 stamp;与位置错误分别保留 |
item | None 或 {"count": int, "stack_id": int, "network_id": int, "attributes_fingerprint": str} |
metadata、effects | 按字段或效果 ID 保存值、known/error/stamp;效果还含 operation/present/amplifier/particles/duration/tick。 |
equipment、attributes | 按装备位置或属性名保存观察;装备含物品与槽位,属性含 value/min/max/defaults/modifiers。 |
metadata_error/effects_error/equipment_error/attributes_error | 各类证据错误;对应 *_error_stamp 保留错误发生时刻。 |
ActorStamp = {"revision": int, "at": str, "packet_id": int},at 是 UTC RFC3339 时间。ActorEvent 含 revision、at、packet_id、kind、runtime_id、unique_id、taker_runtime_id、known、event_type、event_data、health_error、changed_fields 和 error。这是有限保留的事件证据,不是完整移动轨迹;移动更新实体状态而不为每次移动追加这份历史。
绑定实体与订阅变化
python
from neomega_runtime import actor_ref
# snapshot 来自成功的 observe 回执,runtime_id 取自其中的实体。
ref = actor_ref(snapshot, runtime_id)
actor = ref.resolve(new_snapshot)
if actor is not None and actor["position"] is not None:
position = actor["position"]["value"]actor_ref(snapshot, runtime_id) 只绑定有效、存活、可见的实体,否则抛 ValueError。ActorRef 保存 connection、scope、runtime/unique ID 与 Add revision;resolve(snapshot) 返回仍匹配的状态,遇到缺口、不完整快照、死亡、移除或 ID 复用时返回 None。它不刷新观察,也不检查位置年龄,业务仍需检查 stamp。
在 manifest 的 subscriptions 中加入 actor.observed,并由管理员授权后,可从 event.payload["payload"] 读取 ActorObserved。载荷含连接与范围、revision、kind、runtime/unique ID、changed_fields、known/gap/error 及事件字段。kind="source_gap" 的身份和 revision 字段可为 None;收到缺口后重新获取快照,不将缺失数据当作实体消失。事件处理与 ACK 见事件。
用于控制前的身份与时效检查
只比较 runtime ID 不够。同一个数字可能属于不同连接或重新出现的实体;动作前需要比较 connection、scope、runtime/unique ID、Add revision,要求目标仍可见且无死亡证据,并检查 position.stamp.at。sampled_at 更新不能让旧位置变新。
位置按接收顺序投影:绝对移动替换坐标,带绝对轴的增量包替换对应轴,网易小/大增量叠加偏移,缺失轴保留原值。只有旋转或无关包不更新位置 stamp。协议没有服务器 tick,无法识别服务端重排。
移除或明确死亡会清空位置;重新 Add 建立新的位置证据。维度变化清空实体并改变 scope_revision,重连改变 connection_id。未知移动 ID 不创建实体,未收到 Add 的实体不会凭移动包自动出现在快照中。
非法移动会清空该实体位置并保留错误;新的完整绝对坐标可以恢复位置。此时血量和身份仍可能有效,但不能回退使用 spawn_position。连接、身份和保留历史上的失败不能靠一次位置刷新解除。complete=true 也不证明每个实体位置都满足业务时效。
适用范围
此接口覆盖当前观察到的 AddActor / AddItemActor 非玩家身份。玩家名册与 AddPlayer 状态使用玩家流;箭的 owner 元数据、受伤线索、自身死亡与出站动作审计使用动作与战斗观察。掉落物摘要、拾取者 runtime ID 或血量减少都不单独证明物品所有权、攻击者或经济结算。
读取需 framework.actor.observe 权限;订阅需启用原生 gameEvents 来源并授予 actor.observed。控制动作根据当前位置与身份重新校验目标。