Adds the first Part B streams from docs/PROTOCOL_2.md: guild rosters and
town governors ("mayors"), both outbound diff-board sweeps mirroring the
existing champ board.
Overlay:
- BridgeSocial (new): guild sweep+diff over BaseGuild.List -> guild.update /
guild.remove (full-state upsert; disband detected via Disbanded), plus a
real-time guild.join from EventSink.JoinGuild. (EventSink.CreateGuild is only
the load-time factory, so creation is derived sidecar-side from a first-seen
id, as champs do.)
- BridgeGovernance (new): city sweep over CityLoyaltySystem.Cities -> city.update
(governor / governor-elect / election phase), gated on CityLoyaltySystem.Enabled.
- BridgeJson.Actor: shared serial/name/acct/webId/player writer used by both.
- BridgeConfig: GuildSweepSeconds (60s), CitySweepSeconds (300s).
- BridgeBoot: both wired into [bridge reload|sweepnow|status.
Sidecar:
- store: guilds + governors board tables with upsert/delete/all.
- main: route guild.update/remove and city.update into the boards.
- web: GET /guilds, GET /governors served from the store (snapshot-companion
rule, so a fresh page or a restarted sidecar hydrates without the shard).
Docs: INTEGRATION.md event catalog (guild.*, city.update) + board endpoints;
PROTOCOL_2.md Part B phase 1 marked built.
Verified: sidecar cargo check clean; overlay compiles in the full ServUO
Scripts tree (0 errors, 0 warnings). Live end-to-end run still pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
99 lines
4.9 KiB
INI
99 lines
4.9 KiB
INI
|
|
# uo-link bridge settings.
|
|
#
|
|
# Key scope is the filename: Bridge.cfg + StatSweepSeconds => "Bridge.StatSweepSeconds".
|
|
# Read in Configure(), which runs before World.Load.
|
|
|
|
# Loopback only. The socket being local is the trust boundary for inbound commands;
|
|
# if the sidecar ever moves off-host, add a shared secret first.
|
|
Host=127.0.0.1
|
|
Port=7788
|
|
|
|
# Outbound queue cap. On overflow the plugin drops oldest and counts the drops,
|
|
# because a stalled sidecar must never OOM the shard.
|
|
QueueCap=10000
|
|
|
|
# Sweep intervals, seconds. Measured on a 150-character shard: a vitals sweep costs
|
|
# 0.0015 ms/char, so 1000 online players is ~1.5 ms per sweep. See docs/PLAN.md §1.
|
|
StatSweepSeconds=30
|
|
DecaySweepSeconds=60
|
|
EconomySweepSeconds=300
|
|
|
|
# Champion-spawn board poll. ChampionSpawn has no EventSink, so every spawn is diffed on
|
|
# this interval to emit champ.update on any status/level/kills/boss change. The world holds
|
|
# only a handful of spawns, so the pass is trivial; 5-10s is well within site tolerance.
|
|
ChampSweepSeconds=10
|
|
|
|
# Help-page queue poll. The in-game page queue has no EventSink, so it is diffed on this
|
|
# interval to emit page.new / page.closed / page.updated. A few seconds is fine for a
|
|
# support queue; the full open queue is also available on demand via pages.snapshot.
|
|
PageSweepSeconds=5
|
|
|
|
# Guild roster poll (docs/PROTOCOL_2.md Part B). Guilds expose only EventSink.JoinGuild, so
|
|
# create/disband/leave/leader/alliance changes are found by diffing BaseGuild.List on this
|
|
# interval (emit guild.update / guild.remove). Guild membership moves slowly; 60s is ample.
|
|
GuildSweepSeconds=60
|
|
|
|
# Town-governor poll. Each city's Governor / election is diffed on this interval to emit
|
|
# city.update on change. Governors turn over on the order of weeks, so a slow sweep is fine.
|
|
# Idle (emits nothing) unless the City Loyalty system is enabled (CityLoyalty.Enabled).
|
|
CitySweepSeconds=300
|
|
|
|
# Shown to a player when they run [link. The website page where they enter the code.
|
|
LinkUrl=https://yoursite/link
|
|
|
|
# Town-crier news pushed from the website. Caps are defense in depth on top of the
|
|
# loopback trust boundary: a buggy or compromised sidecar still cannot flood the criers.
|
|
TownCrierMaxLines=6
|
|
TownCrierMaxLineLength=200
|
|
TownCrierMaxActive=20
|
|
TownCrierMaxDurationSec=86400
|
|
|
|
# Admin write plane (staff moderation from the website). OFF by default: the whole
|
|
# feature is opt-in per shard. When enabled, inbound admin.* commands (kick/ban/unban/
|
|
# broadcast) are honored. Authorization is enforced on the website; the shard trusts the
|
|
# loopback socket and applies a hard floor below.
|
|
AdminWriteEnabled=false
|
|
|
|
# The one shard-side safety floor. An admin.* command refuses any target whose AccessLevel
|
|
# is at or above this, so even a compromised sidecar can never touch the Owner. Values are
|
|
# AccessLevel names (Player, VIP, Counselor, Decorator, Spawner, GameMaster, Seer,
|
|
# Administrator, Developer, CoOwner, Owner). Default CoOwner => only Owner/CoOwners shielded.
|
|
AdminAccessFloor=CoOwner
|
|
|
|
# Defense-in-depth caps on admin.* payloads (mirroring the town-crier caps).
|
|
AdminBroadcastMaxLength=300
|
|
AdminReasonMaxLength=400
|
|
# Clamp on a timed ban's duration, seconds. A ban with no/zero duration is indefinite.
|
|
AdminBanMaxDurationSec=31536000
|
|
|
|
# Account provisioning (docs/PROTOCOL_2.md Part A). Which side may mint game accounts:
|
|
# website — the website is the authority; pair with Accounts.AutoCreateAccounts=false
|
|
# (else an in-game login of any new name still mints an account).
|
|
# game — the game server is the authority; website account.create is refused.
|
|
# hybrid — either side may create (the default).
|
|
# The bridge governs only the account.create verb; the in-game first-login auto-create is
|
|
# the core Accounts.AutoCreateAccounts setting, which you pair with the mode above. On boot
|
|
# the bridge warns if the two contradict. An unrecognized value here falls back to 'game'
|
|
# (the safest — no website creation).
|
|
SignupMode=hybrid
|
|
|
|
# Master switch for the account.create verb. Absent, it follows the mode (on unless
|
|
# SignupMode=game). Set explicitly to force it on or off regardless of mode.
|
|
AccountCreateEnabled=true
|
|
|
|
# Fail closed if account.create omits a usable browser IP. The per-IP cap
|
|
# (Accounts.AccountsPerIp) only means something if a missing/loopback IP is refused rather
|
|
# than waved through. Turn off only for a deployment that deliberately does not cap website
|
|
# signups by IP (MaxAccountsPerIP still applies in-game either way).
|
|
RequireIpForCreate=true
|
|
|
|
# Length caps on a website-supplied username / password, checked before the account is made.
|
|
AccountNameMaxLength=16
|
|
AccountPasswordMaxLength=30
|
|
|
|
# The test scaffolding in tools/scaffolding/ reads its own flags from this file
|
|
# (SeedOnStart, CensusOnStart, ProbeOnStart). They are absent here on purpose:
|
|
# Config.Get returns the default of false when a key is missing, so a deployed
|
|
# server never runs the scaffolding even if its .cs files are present.
|