NEO-121: Address review nits for quest telemetry hook sites.
Add schemaVersion to quest_start comment, thread playerId/questId into DenyAccept, and merge duplicate deny snapshot helpers.pull/160/head
parent
89affe2b32
commit
88d01778a1
|
|
@ -56,7 +56,7 @@
|
||||||
- **`quest_start`:** after successful **`TryActivate`** in **`TryAccept`**.
|
- **`quest_start`:** after successful **`TryActivate`** in **`TryAccept`**.
|
||||||
- **`quest_step_complete`:** after successful **`TryAdvanceStep`** store commit.
|
- **`quest_step_complete`:** after successful **`TryAdvanceStep`** store commit.
|
||||||
- **`quest_complete`:** after first-time **`TryMarkComplete`** commit (not idempotent replay).
|
- **`quest_complete`:** after first-time **`TryMarkComplete`** commit (not idempotent replay).
|
||||||
- **`quest_accept_denied`:** **`DenyAccept`** helper on all **`TryAccept`** deny paths.
|
- **`quest_accept_denied`:** **`DenyAccept(playerId, questId, …)`** on all **`TryAccept`** deny paths; optional accept context on **`DenyFromProgressSnapshot`** for activate-failure rereads.
|
||||||
- **Docs:** `server/README.md` quest telemetry subsection; E7.M1 module + alignment register + E7M1 backlog updated.
|
- **Docs:** `server/README.md` quest telemetry subsection; E7.M1 module + alignment register + E7M1 backlog updated.
|
||||||
- **Manual QA:** `docs/manual-qa/NEO-121.md`.
|
- **Manual QA:** `docs/manual-qa/NEO-121.md`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,9 @@ NEO-121 adds **comment-only** E9.M1 telemetry hook sites to **`QuestStateOperati
|
||||||
|
|
||||||
## Nits
|
## Nits
|
||||||
|
|
||||||
1. **Nit:** Plan technical approach lists optional **`schemaVersion`** in **`quest_start`** planned payload; the inline comment omits it. Harmless for comment-only work; consider adding for parity when touching the file again.
|
1. ~~**Nit:** Plan technical approach lists optional **`schemaVersion`** in **`quest_start`** planned payload; the inline comment omits it. Harmless for comment-only work; consider adding for parity when touching the file again.~~ **Done.** Added optional **`schemaVersion`** to **`quest_start`** inline comment.
|
||||||
|
|
||||||
2. **Nit:** **`DenyFromProgressSnapshotAccept`** duplicates **`DenyFromProgressSnapshot`** except for **`DenyAccept`** vs **`Deny`** — intentional funneling, but E9.M1 wiring may want **`playerId`** / **`questId`** threaded into **`DenyAccept`** (comment already documents those fields; implementer will need caller context).
|
2. ~~**Nit:** **`DenyFromProgressSnapshotAccept`** duplicates **`DenyFromProgressSnapshot`** except for **`DenyAccept`** vs **`Deny`** — intentional funneling, but E9.M1 wiring may want **`playerId`** / **`questId`** threaded into **`DenyAccept`** (comment already documents those fields; implementer will need caller context).~~ **Done.** Merged into **`DenyFromProgressSnapshot`** with optional accept-deny context; **`DenyAccept`** now takes **`playerId`** and **`questId`** at all call sites.
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,22 +25,22 @@ public static class QuestStateOperations
|
||||||
if (!questRegistry.TryNormalizeKnown(questId, out var normalizedQuestId) ||
|
if (!questRegistry.TryNormalizeKnown(questId, out var normalizedQuestId) ||
|
||||||
!questRegistry.TryGetDefinition(normalizedQuestId, out var definition))
|
!questRegistry.TryGetDefinition(normalizedQuestId, out var definition))
|
||||||
{
|
{
|
||||||
return DenyAccept(QuestStateReasonCodes.UnknownQuest);
|
return DenyAccept(playerId, questId, QuestStateReasonCodes.UnknownQuest);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!progressStore.CanWritePlayer(playerId))
|
if (!progressStore.CanWritePlayer(playerId))
|
||||||
{
|
{
|
||||||
return DenyAccept(QuestStateReasonCodes.UnknownPlayer);
|
return DenyAccept(playerId, normalizedQuestId, QuestStateReasonCodes.UnknownPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progressStore.TryGetProgress(playerId, normalizedQuestId, out var existing))
|
if (progressStore.TryGetProgress(playerId, normalizedQuestId, out var existing))
|
||||||
{
|
{
|
||||||
if (existing.Status == QuestProgressStatus.Completed)
|
if (existing.Status == QuestProgressStatus.Completed)
|
||||||
{
|
{
|
||||||
return DenyAccept(QuestStateReasonCodes.AlreadyCompleted, existing);
|
return DenyAccept(playerId, normalizedQuestId, QuestStateReasonCodes.AlreadyCompleted, existing);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DenyAccept(QuestStateReasonCodes.AlreadyActive, existing);
|
return DenyAccept(playerId, normalizedQuestId, QuestStateReasonCodes.AlreadyActive, existing);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var prerequisiteId in definition.PrerequisiteQuestIds)
|
foreach (var prerequisiteId in definition.PrerequisiteQuestIds)
|
||||||
|
|
@ -48,7 +48,7 @@ public static class QuestStateOperations
|
||||||
if (!progressStore.TryGetProgress(playerId, prerequisiteId, out var prerequisite) ||
|
if (!progressStore.TryGetProgress(playerId, prerequisiteId, out var prerequisite) ||
|
||||||
prerequisite.Status != QuestProgressStatus.Completed)
|
prerequisite.Status != QuestProgressStatus.Completed)
|
||||||
{
|
{
|
||||||
return DenyAccept(QuestStateReasonCodes.PrerequisiteIncomplete);
|
return DenyAccept(playerId, normalizedQuestId, QuestStateReasonCodes.PrerequisiteIncomplete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,7 +56,8 @@ public static class QuestStateOperations
|
||||||
{
|
{
|
||||||
// --- Telemetry hook site (NEO-121): future E9.M1 catalog event `quest_start` ---
|
// --- Telemetry hook site (NEO-121): future E9.M1 catalog event `quest_start` ---
|
||||||
// TODO(E9.M1): catalog emit — first activation only (deny paths excluded).
|
// TODO(E9.M1): catalog emit — first activation only (deny paths excluded).
|
||||||
// Planned payload fields: playerId, questId, currentStepIndex (0). No ingest or ILogger here (comments-only).
|
// Planned payload fields: playerId, questId, currentStepIndex (0), optional schemaVersion.
|
||||||
|
// No ingest or ILogger here (comments-only).
|
||||||
|
|
||||||
QuestObjectiveWiring.TryProcessInventoryHasItemForQuest(
|
QuestObjectiveWiring.TryProcessInventoryHasItemForQuest(
|
||||||
playerId,
|
playerId,
|
||||||
|
|
@ -224,11 +225,11 @@ public static class QuestStateOperations
|
||||||
string playerId,
|
string playerId,
|
||||||
string questId,
|
string questId,
|
||||||
QuestStepState attemptSnapshot) =>
|
QuestStepState attemptSnapshot) =>
|
||||||
DenyFromProgressSnapshotAccept(attemptSnapshot, QuestStateReasonCodes.AlreadyActive)
|
DenyFromProgressSnapshot(attemptSnapshot, QuestStateReasonCodes.AlreadyActive, playerId, questId)
|
||||||
?? (progressStore.TryGetProgress(playerId, questId, out var reread)
|
?? (progressStore.TryGetProgress(playerId, questId, out var reread)
|
||||||
? DenyFromProgressSnapshotAccept(reread, QuestStateReasonCodes.AlreadyActive)
|
? DenyFromProgressSnapshot(reread, QuestStateReasonCodes.AlreadyActive, playerId, questId)
|
||||||
: null)
|
: null)
|
||||||
?? DenyAccept(QuestStateReasonCodes.UnknownPlayer);
|
?? DenyAccept(playerId, questId, QuestStateReasonCodes.UnknownPlayer);
|
||||||
|
|
||||||
private static QuestStateOperationResult DenyAdvanceFailure(
|
private static QuestStateOperationResult DenyAdvanceFailure(
|
||||||
IPlayerQuestStateStore progressStore,
|
IPlayerQuestStateStore progressStore,
|
||||||
|
|
@ -244,7 +245,9 @@ public static class QuestStateOperations
|
||||||
|
|
||||||
private static QuestStateOperationResult? DenyFromProgressSnapshot(
|
private static QuestStateOperationResult? DenyFromProgressSnapshot(
|
||||||
QuestStepState? snapshot,
|
QuestStepState? snapshot,
|
||||||
string activeOrIntermediateReasonCode)
|
string activeOrIntermediateReasonCode,
|
||||||
|
string? acceptDenyPlayerId = null,
|
||||||
|
string? acceptDenyQuestId = null)
|
||||||
{
|
{
|
||||||
if (snapshot is null)
|
if (snapshot is null)
|
||||||
{
|
{
|
||||||
|
|
@ -253,34 +256,16 @@ public static class QuestStateOperations
|
||||||
|
|
||||||
if (snapshot.Status == QuestProgressStatus.Completed)
|
if (snapshot.Status == QuestProgressStatus.Completed)
|
||||||
{
|
{
|
||||||
return Deny(QuestStateReasonCodes.AlreadyCompleted, snapshot);
|
return acceptDenyPlayerId is not null
|
||||||
|
? DenyAccept(acceptDenyPlayerId, acceptDenyQuestId ?? string.Empty, QuestStateReasonCodes.AlreadyCompleted, snapshot)
|
||||||
|
: Deny(QuestStateReasonCodes.AlreadyCompleted, snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snapshot.Status == QuestProgressStatus.Active)
|
if (snapshot.Status == QuestProgressStatus.Active)
|
||||||
{
|
{
|
||||||
return Deny(activeOrIntermediateReasonCode, snapshot);
|
return acceptDenyPlayerId is not null
|
||||||
}
|
? DenyAccept(acceptDenyPlayerId, acceptDenyQuestId ?? string.Empty, activeOrIntermediateReasonCode, snapshot)
|
||||||
|
: Deny(activeOrIntermediateReasonCode, snapshot);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static QuestStateOperationResult? DenyFromProgressSnapshotAccept(
|
|
||||||
QuestStepState? snapshot,
|
|
||||||
string activeOrIntermediateReasonCode)
|
|
||||||
{
|
|
||||||
if (snapshot is null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snapshot.Status == QuestProgressStatus.Completed)
|
|
||||||
{
|
|
||||||
return DenyAccept(QuestStateReasonCodes.AlreadyCompleted, snapshot);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snapshot.Status == QuestProgressStatus.Active)
|
|
||||||
{
|
|
||||||
return DenyAccept(activeOrIntermediateReasonCode, snapshot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -289,11 +274,16 @@ public static class QuestStateOperations
|
||||||
private static QuestStateOperationResult Success(QuestStepState snapshot) =>
|
private static QuestStateOperationResult Success(QuestStepState snapshot) =>
|
||||||
new(Success: true, ReasonCode: null, Snapshot: snapshot);
|
new(Success: true, ReasonCode: null, Snapshot: snapshot);
|
||||||
|
|
||||||
private static QuestStateOperationResult DenyAccept(string reasonCode, QuestStepState? snapshot = null)
|
private static QuestStateOperationResult DenyAccept(
|
||||||
|
string playerId,
|
||||||
|
string questId,
|
||||||
|
string reasonCode,
|
||||||
|
QuestStepState? snapshot = null)
|
||||||
{
|
{
|
||||||
// --- Telemetry hook site (NEO-121): future E9.M1 catalog event `quest_accept_denied` ---
|
// --- Telemetry hook site (NEO-121): future E9.M1 catalog event `quest_accept_denied` ---
|
||||||
// TODO(E9.M1): catalog emit — reasonCode from QuestStateReasonCodes (unknown_quest, prerequisite_incomplete, etc.).
|
// TODO(E9.M1): catalog emit — reasonCode from QuestStateReasonCodes (unknown_quest, prerequisite_incomplete, etc.).
|
||||||
// Planned payload fields: playerId, questId, reasonCode. No ingest or ILogger here (comments-only).
|
// Planned payload fields: playerId, questId, reasonCode (caller context threaded for E9.M1 wiring).
|
||||||
|
// No ingest or ILogger here (comments-only).
|
||||||
|
|
||||||
return Deny(reasonCode, snapshot);
|
return Deny(reasonCode, snapshot);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue