feat(bridge)!: guild rosters and per-member leaves, on protocol 4 #12
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/teams-phase1-guild-roster"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Teams Phase 1, shard half. Targets
edge;edge→mainis the v4 cutover.Spec:
docs/link/v4.md· plan:docs/website/TEAMS.mdPart 12 Phase 1What
Protocol 2 could say how many members a guild had, not who they were, and ServUO raises no event for leaving a guild — so
PROTOCOL_2.md§10.1 deferred the membership half. This builds it.The sweep holds each guild's member serial set instead of folding it into the signature as a sum. A set comparison cannot collide, where a sum could: one member joining and another leaving between two passes offset each other and the guild looked unchanged. And a set can be differenced, which is what makes a per-member
guild.leavepossible without a core tap.A changed set also re-emits
guild.roster, the full member list, so departures stay advisory — a consumer holding a membership table never has to replay deltas to stay correct.Frames are capped
A roster is the only fat frame this plugin emits — measured at ~69 bytes/member against a real 155-member guild — and the sidecar's
read_linehas no length bound. Members per frame are capped (default 500 ≈ 35 KB); a guild over the cap splits into frames carryingseq/more/total. Every realistic guild emits one frame withseq: 0, more: false, the same shape as if chunking did not exist.The reconnect baseline is spread
OnConnectedclears the diff caches, so every guild reads as changed at once. At mostGuildRosterGuildsPerTickguilds (default 25) emit a roster per sweep, and the sweep re-arms after 2s while draining — so catch-up takes seconds rather than one full sweep interval per batch.Notes for review
overlay.tomlprotocol → 4 is in this PR deliberately. CI folds it into the release manifest and the installer refuses to pair an overlay and sidecar that disagree, so a bump landing separately would silently fail to compose into a bundle.BridgeJsonhad no array writer at all — no way to express a list of objects.Actoris split into a bare-object writer so both the single and array forms can share it.acct/webIdare emitted unconditionally by design: the sidecar is a forwarder and the website projects per the visibility rungs.Verification
This repo has no CI build — the plugin compiles only inside ServUO — so "it compiled" is not evidence. Run against a live ServUO shard and the real Rust sidecar (not a stub):
PlayerMobiles; cap forced to 50 so the split path fired → 50/50/50/5 across four frames,seq0–3,morefalse only on the last.guild.leaveframes with the correct serials, and a re-emitted roster attotal: 153with both absent.guild.update's name/abbr/counts intact beside it.Still outstanding for the cutover: the five-rung shard visibility walk.
AI-assisted: written with Claude Code. Commits carry
Co-Authored-By: Claude <noreply@anthropic.com>.