Skip to main content

Quests & Progress

Progress tracking is a lookup-by-owner workload with a simple state flip. It shows how a declared index keeps per-player reads fast and how a command performs the write.

note

The QuestProgress table here is the same one introduced in Build Your First Game; this page adds the GetOpenQuests query and the CompleteQuest command on top of it.

Schema

table QuestProgress(plural: QuestProgressRows, persistence: local, capacity: 2048, type_id: 3) {
Id: int @id
PlayerId: int
QuestId: int
Completed: bool

@@index(fields: [PlayerId], name: "QuestProgress_ByPlayer", kind: lookup)
}

Query the player's open quests

query GetOpenQuests(playerId: int) -> QuestProgress[] {
from QuestProgressRows
| filter PlayerId == @playerId && Completed == false
| sort QuestId
}

The lookup index on PlayerId means this filter is a direct index probe, not a table scan — even with thousands of rows.

Complete a quest with a command

module Quests {
command CompleteQuest(playerId: int, questId: int) -> CompleteQuestResult
kind local
{
upsert QuestProgressRows
| key { PlayerId: playerId, QuestId: questId }
| set Completed = true

return { questId: questId }
}
}

Call it from C#

using ConjureDB;

using var ctx = DbContextBuilder<GameDbContext>.Create()
.WithDataDirectory("./data")
.WithDefaultSnapshot()
.Build();

var open = ctx.GetOpenQuests(playerId: 1);

See Indexing for how to choose lookup vs sorted_set / sorted_list vs unique indexes for each access pattern.