feat(protocol2): presence stream — online population + region transitions (Part B ph.2)

Overlay BridgePresence (new):
- presence.online sweep over online PlayerMobiles: total plus per-facet and
  per-region counts, emitted only when the population changes.
- region.enter real-time from EventSink.OnEnterRegion (player-filtered), the
  cheap location signal PLAN.md prefers over Movement.
- PresenceSweepSeconds (30s); wired into [bridge reload|sweepnow|status.

Sidecar:
- GET /online serves the latest presence.online snapshot from the event store
  (survives restart); population time series via /history?kind=presence.online.

Docs: INTEGRATION.md presence events + /online endpoint; PROTOCOL_2 ph.2 built.

Verified: sidecar cargo check clean; overlay compiles in the full ServUO
Scripts tree (0 errors, 0 warnings). Live run pending.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-17 08:02:05 -05:00
parent dd39d524c6
commit 1244eb6c4f
4 changed files with 226 additions and 0 deletions

View File

@@ -163,6 +163,7 @@ namespace Server.Custom.Bridge
BridgeChamps.Rearm();
BridgeSocial.Rearm();
BridgeGovernance.Rearm();
BridgePresence.Rearm();
e.Mobile.SendMessage("Bridge: {0}", BridgeConfig.Describe());
e.Mobile.SendMessage("Bridge: sweeps re-armed; endpoint changes take effect on reconnect.");
break;
@@ -177,11 +178,13 @@ namespace Server.Custom.Bridge
BridgeChamps.SweepOnce();
BridgeSocial.SweepOnce();
BridgeGovernance.SweepOnce();
BridgePresence.SweepOnce();
e.Mobile.SendMessage("Bridge: ran one sweep of each stream.");
e.Mobile.SendMessage("Bridge: {0}", BridgeSweeps.Status());
e.Mobile.SendMessage("Bridge: {0}", BridgeChamps.Status());
e.Mobile.SendMessage("Bridge: {0}", BridgeSocial.Status());
e.Mobile.SendMessage("Bridge: {0}", BridgeGovernance.Status());
e.Mobile.SendMessage("Bridge: {0}", BridgePresence.Status());
break;
default:
@@ -194,6 +197,7 @@ namespace Server.Custom.Bridge
e.Mobile.SendMessage("Bridge: {0}", BridgeChamps.Status());
e.Mobile.SendMessage("Bridge: {0}", BridgeSocial.Status());
e.Mobile.SendMessage("Bridge: {0}", BridgeGovernance.Status());
e.Mobile.SendMessage("Bridge: {0}", BridgePresence.Status());
e.Mobile.SendMessage("Bridge: {0}", BridgePages.Status());
break;
}