计划执行与检查节点
executing-plans
按既定实施计划完成工作,保持过程检查和反馈。
interest-management【效率与协作】Expert network interest management — visibility graphs, observer sets, replicated-state throttling, event queues and scope control for scalable multiplayer servers.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Nobody needs everything. A 100-player battle server could broadcast 6 MB/s to everyone — unviable. Interest management (IM) decides who gets what, at what rate, with the least CPU — turning O(players²) broadcast into near-O(visible) traffic.
IM solves state (per-entity rate, per-observer mask). Events live in a separate reliable queue (see event-queue).
observer O (a client)
interest(O) = { entities E : dist(O,E) <= radius && comesFrom(visibility(O,E)) && O.state needs }
Two classic models:
| Model | Idea | Cost |
|---|---|---|
| Spatial (distance/relevance) | entities within radius get replicated | cheap; dumb (sees through walls) |
| Visibility/occlusion | only what O's camera/query can see | accurate; more compute |
| Hybrid (recommended) | spatial first, then per-entity relevance mask | standard |
Each entity has a bitmask of actor channels (movement, HP, items, emotes). Each observer subscribes to channels; IM intersects: interest = entitiesNear(O) ∩ channels(O) ∩ channels(E).
Per-channel update rates may differ (see §5), so a snapshot packet = union of per-channel deltas.
game-engine/math-foundation collision refs).Recomputing all interests every frame is wasteful. Cache:
scopeCache[O] = {lastRecomputeTick, recomputeThreshold}
if E moved out of O's radius → remove
if E entered radius and channel matches → add
Different data needs different frequencies:
| Channel | Rate | Why |
|---|---|---|
| movement | 30–60 Hz | smoothness |
| HP/mana | 10–20 Hz | low change |
| items/emote | 4–10 Hz | occasional |
| spell effects (critical) | reliable + on-event | must-arrive |
Cost trick: detail reduces with distance (network LOD): entity at 200 m → movement 10 Hz, no HP, no inventory; at 10 m → full rate. This is the network analog of render LOD (see scaling-architecture).
Server per-observer maintains:
dirtyIds (entities changed since last send to that observer).replicated map (entityId → last sent tick or channel version).Send loop per observer (draw FPS cost):
for id in valueSet(interestedIntersection dirty):
send delta bytes for changed channels (quantized)
Complexity ≈ O(|interest(O)|) per observer, per tick — a per-observer packet builder that stops early on a byte budget (see world-state-snapshot budgets).
| Type | Transport | Policy |
|---|---|---|
| replicated state (transform, hp) | unreliable (UDP) | latest wins; loss = just staler |
| events (kill, spawn, loot) | reliable (UDP+ACK) | must arrive once, in order |
Never put rare-events on the lossy channel (missed "you won" = rage). Events go through the event queue with an ACK list; on disconnect, replay the unACKed.
If a snapshot would exceed the per-observer byte budget:
| Metric | Budget |
|---|---|
| interest recompute | amortized per movement, not per tick |
| per-observer send loop | < 0.05 ms |
| memory for scope cache | ≤ a few MB |
| packet bytes/clients | the real cost — [interest solves the multiplier] |
If the world is huge (open MMO), shard by region rather than interest-only (a view range cap). IM keeps each node's traffic sane; region sharding adds node splitting (see scaling-architecture).
references/visibility-and-spatial.md — grids, spatial hashes, frustum pre-step, recompute thresholdsreferences/observer-sets.md — scope cache, relevance masks, channel interestsreferences/network-lod.md — per-channel rates, distance LOD, quantization coarseningreferences/event-queue.md — reliable event queue, ordering, ACK, replay on disconnectreferences/state-vs-event-replication.md — latest-wins vs once-only channels, the split decisionreferences/budgeting-and-prioritization.md — byte budgets, priority drop lists, aggregation