Class WaypointUnlockMask
The waypoints a character has discovered in one scene, as a growable bit set: bit
N of page N / 64 is set when waypoint N is unlocked.
public sealed class WaypointUnlockMask
- Inheritance
-
WaypointUnlockMask
- Inherited Members
Remarks
Why a bit set. A scene has tens of waypoints, every character eventually
unlocks most of them, and the whole set is read and written together: on login, in the
spawn payload, and on save. One row per (character, waypoint) would be a forty-byte row for
a single bit; the set stores those bits as bits. The same shape is on the wire and in the
database (character_waypoints, one row per non-empty page), so nothing translates
between representations — see CharacterDialogueChoiceData for the precedent.
Why pages. A single 64-bit word would cap a scene at 64 waypoints, and the day that cap is hit is the day a designer's sixty-fifth waypoint silently fails to persist. Pages make the set unbounded (to MaxIndex, a sanity cap on authoring rather than on storage) at the cost of one extra small integer per row.
Persistence without a version. Bits are only ever set, and the database merge
is an OR. So "what still needs writing" is exactly unlocked & ~persisted, and
confirming a write is persisted |= written; a bit set while a write was in flight is
not in written and stays dirty. No counter to bump and no stale-confirmation hazard —
the trap the versioned tables fell into (see the attribute/ability persistence notes).
Fields
BitsPerPage
Bits per page. A page is one ulong and one database row.
public const int BitsPerPage = 64
Field Value
MaxIndex
Highest waypoint index a scene may author. Sixteen pages. A bound on authoring mistakes and on what a payload may ask the controller to allocate, not a design limit anyone is expected to reach.
public const int MaxIndex = 1023
Field Value
MaxPages
Most pages a scene can have, derived from MaxIndex.
public const int MaxPages = 16
Field Value
Properties
IsDirty
Whether any page is dirty.
public bool IsDirty { get; }
Property Value
IsEmpty
Whether no waypoint is unlocked.
public bool IsEmpty { get; }
Property Value
PageCount
Number of pages allocated. Trailing pages may be empty.
public int PageCount { get; }
Property Value
Methods
Add(int)
Unlocks a waypoint.
public bool Add(int waypointIndex)
Parameters
waypointIndexint
Returns
- bool
True when the bit was newly set; false when it was already set or the index is invalid.
BitOf(int)
The bit an index occupies within its page.
public static ulong BitOf(int waypointIndex)
Parameters
waypointIndexint
Returns
Clear()
Drops everything.
public void Clear()
CollectDirtyPages(string, List<WaypointPageSnapshot>)
Appends every page with unconfirmed bits.
public void CollectDirtyPages(string sceneName, List<WaypointPageSnapshot> results)
Parameters
sceneNamestringThe scene, stamped onto each snapshot.
resultsList<WaypointPageSnapshot>Receives the dirty pages.
Contains(int)
Whether a waypoint is unlocked.
public bool Contains(int waypointIndex)
Parameters
waypointIndexint
Returns
GetPage(int)
The unlocked bits of a page. Zero for a page beyond the allocated range.
public ulong GetPage(int page)
Parameters
pageint
Returns
IsPageDirty(int)
Whether any bit of a page has not been confirmed by the database.
public bool IsPageDirty(int page)
Parameters
pageint
Returns
IsValidIndex(int)
Whether an index is within [0, MaxIndex].
public static bool IsValidIndex(int waypointIndex)
Parameters
waypointIndexint
Returns
MarkPersisted(int, ulong)
Records that the database holds these bits of a page.
public void MarkPersisted(int page, ulong writtenMask)
Parameters
PageOf(int)
Which page an index lives on.
public static int PageOf(int waypointIndex)
Parameters
waypointIndexint
Returns
Restore(int, ulong)
Installs persisted bits: unlocked and already confirmed, so they are not dirty.
public void Restore(int page, ulong mask)
Parameters
Remarks
OR-ed in, never assigned. A restore arriving after an unlock in the same session (a slow load racing a quick interaction) must not drop the unlock; and on the owner client the payload may be re-read on a pooled respawn.