跳转到正文

实体观察 ​

使用 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) -> OperationIntent

Actors 与下文类型从 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、eventsActorState[] 与 ActorEvent[]

ActorState 中所有 ID 均为十进制字符串:

字段类型与含义
runtime_id、unique_id、entity_type当前观察身份及实体类型
spawn_position最近 Add 包中的三维坐标列表,不能代替缺失的当前位置
positionNone 或 {"value": [x,y,z], "stamp": ActorStamp}
position_error、position_error_stamp位置错误及对应 stamp;无 stamp 时为 None
visible、added、removed、death可见状态、Add stamp、移除或明确死亡 stamp;后二者可为 None
healthNone 或 {"value": float, "min": float, "max": float, "stamp": ActorStamp}
health_error、health_error_stamp血量错误及对应 stamp;与位置错误分别保留
itemNone 或 {"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。控制动作根据当前位置与身份重新校验目标。

Neomega · 使用、开发与参考文档