Phase 3: polled sweeps (vitals, house decay, economy)
BridgeSweeps runs three repeating Core-thread timers for the state that has no
EventSink. Cost measured in Phase 1 is why they can run on the main thread: a
full pass of all three is well under a millisecond at the seeded scale.
- Vitals: online players only. Small and volatile; the sidecar diffs snapshots.
Offline characters do not move, so they are served on demand as full profiles
instead, not swept.
- House decay: emits only on a level transition. A silent baseline on
ServerStarted records every house's current stage, so a restart does not
re-announce them. Payload carries from/to, coords, nested ban location,
region, sign name, owner serial+account, and built/refreshed timestamps, all
null-guarded.
- Economy supply: periodic sum of every account's currency as a snapshot. The
level; AccountGoldChange and the vendor events are the flow.
All three re-arm on `[bridge reload`; `[bridge sweepnow` runs one of each on
demand; `[bridge status` reports sweep counters. Sweeps skip emitting while the
sidecar is disconnected, since their state is perishable and re-emitted next
tick anyway (unlike events, which queue through an outage).
Verified on the seeded world with 8s intervals: baseline recorded 29 houses
silently, a probe bumped one Somewhat->Fairly, and the next sweep emitted exactly
one house.decay and none for the other 28. Economy emitted a supply snapshot per
interval. Vitals emitted nothing, correctly, since all seeded characters are
offline. Evidence in docs/PLAN.md §13.
Adds tools/scaffolding/BridgeSweepProbe.cs (never deployed) to force a decay
transition on demand.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
70
tools/scaffolding/BridgeSweepProbe.cs
Normal file
70
tools/scaffolding/BridgeSweepProbe.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Server.Multis;
|
||||
|
||||
namespace Server.Custom
|
||||
{
|
||||
/// <summary>
|
||||
/// Forces a house-decay transition so the decay sweep's transition detection can be
|
||||
/// observed without waiting out a real 12–24 h IDOC stage.
|
||||
///
|
||||
/// After the bridge takes its silent baseline on ServerStarted, this bumps one condemned
|
||||
/// seeded house one stage further with SetDynamicDecay. The next decay sweep should see the
|
||||
/// level change and emit exactly one house.decay.
|
||||
///
|
||||
/// Test scaffolding. Never deployed. Only meaningful against the seeded world.
|
||||
/// </summary>
|
||||
public static class BridgeSweepProbe
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
if (Config.Get("Bridge.SweepProbeOnStart", false))
|
||||
EventSink.ServerStarted += () => Timer.DelayCall(TimeSpan.FromSeconds(6.0), Run);
|
||||
}
|
||||
|
||||
private static void Run()
|
||||
{
|
||||
try
|
||||
{
|
||||
BaseHouse target = null;
|
||||
DecayLevel current = DecayLevel.Ageless;
|
||||
|
||||
// Find a house already decaying (not Ageless/LikeNew), so a bump is a real move.
|
||||
foreach (var h in BaseHouse.AllHouses)
|
||||
{
|
||||
if (h == null || h.Deleted)
|
||||
continue;
|
||||
|
||||
var lvl = h.DecayLevel;
|
||||
|
||||
if (lvl == DecayLevel.Greatly || lvl == DecayLevel.Fairly || lvl == DecayLevel.Somewhat)
|
||||
{
|
||||
target = h;
|
||||
current = lvl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
Console.WriteLine("[SweepProbe] no decaying house found to bump");
|
||||
return;
|
||||
}
|
||||
|
||||
var next = current + 1; // e.g. Somewhat -> Fairly -> Greatly -> IDOC
|
||||
|
||||
Console.WriteLine("[SweepProbe] bumping house 0x{0:X} from {1} to {2}",
|
||||
target.Serial.Value, current, next);
|
||||
|
||||
target.SetDynamicDecay(next);
|
||||
|
||||
Console.WriteLine("[SweepProbe] done; the next decay sweep should emit house.decay");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("[SweepProbe] FAILED: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ These two scripts produced the measured budget in `docs/PLAN.md` §1. They are k
|
||||
| `BridgeSeeder.cs` | `Scripts/Custom/BridgeSeeder.cs` | Populates a synthetic world: 50 accounts, 150 characters, 30 houses, 30 player vendors with 40 listings each. |
|
||||
| `BridgeProbe.cs` | `Scripts/Custom/BridgeProbe.cs` | Times every read the plugin performs, on the Core thread. Read-only. |
|
||||
| `BridgeEventProbe.cs` | `Scripts/Custom/BridgeEventProbe.cs` | Fires gold/fame/karma/save events through their real code paths so the emit path can be verified without a game client. **Mutates the world and saves.** Flag: `EventProbeOnStart`. |
|
||||
| `BridgeSweepProbe.cs` | `Scripts/Custom/BridgeSweepProbe.cs` | Bumps one seeded house's decay stage after baseline so the decay sweep's transition detection can be observed without waiting a real IDOC stage. Flag: `SweepProbeOnStart`. Pair with short `*SweepSeconds` overrides. |
|
||||
|
||||
## Deploy overwrites Bridge.cfg
|
||||
|
||||
|
||||
Reference in New Issue
Block a user