feat(quest): QT6 — plugins can read the contract tracker
The last piece of QT6's own scope: r10-quest-dialogs.md §11.6's contract half. IGameState.Contracts exposes what the client structurally knows about quests, which — per that same research — is the tracker and nothing else. The rest of §11.6 (chat stream, tells, give, use, confirmations) is other features and stays out of this campaign. A pull-through source rather than a pushed mirror. Contracts change rarely and are already owned canonically, so a second copy would only be a thing to keep in step; reading through means a plugin cannot observe a stale list. Both hosts implement it. The headless one carries contract id, stage and progress but no names — a bot has no dat access — because losing the TEXT is expected while losing the QUEST would leave a bot silently unable to see what it is on. Same rule covers a contract the installed dat has never heard of: it still projects, with empty text and a correct status, rather than vanishing. The interface member is defaulted so a host predating this campaign still satisfies IGameState. Two lazy catalog loads exist (the panel's and this one) rather than one shared instance. That is deliberate: threading a shared ContractCatalog through three composition records to avoid reading a 322-row immutable table at most twice per session would be plumbing for no correctness or performance gain, and the comment at the call site says so. Campaign QT is complete; the connected user gate is owed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
56beeb720d
commit
fe1e68e5fe
8 changed files with 305 additions and 0 deletions
|
|
@ -278,6 +278,30 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
d.DatLock,
|
||||
world.TerrainBuild.HeightTable,
|
||||
d.Options.DumpSceneryZ);
|
||||
// Campaign QT slice QT6: the plugin-facing contract view. A
|
||||
// pull-through source rather than a mirror, so a plugin always reads
|
||||
// the canonical tracker instead of a copy that could fall behind it.
|
||||
//
|
||||
// The catalog is loaded lazily and independently of the Journal
|
||||
// panel's own. Two reads of a 322-row immutable table across a whole
|
||||
// session is not worth threading a shared instance through three
|
||||
// composition records for; correctness is identical either way.
|
||||
AcDream.Core.Quests.ContractCatalog? pluginContractCatalog = null;
|
||||
d.WorldGameState.ContractsSource = () =>
|
||||
{
|
||||
if (pluginContractCatalog is null)
|
||||
{
|
||||
lock (d.DatLock)
|
||||
pluginContractCatalog =
|
||||
AcDream.Content.ContractTableReader.Load(content.Dats);
|
||||
}
|
||||
|
||||
return AcDream.Runtime.Gameplay.ContractPluginProjection.Project(
|
||||
d.Runtime.ContractsOwner.View,
|
||||
pluginContractCatalog,
|
||||
DateTime.UtcNow);
|
||||
};
|
||||
|
||||
var streamerLease = scope.Acquire(
|
||||
"landblock streamer",
|
||||
() => LandblockStreamer.CreateForRequests(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue