File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -140,6 +140,11 @@ private void addDrawable(DrawableHitObject drawable)
140140 // Binary-search insertion to keep aliveObjectsSortedCache in StartTime order.
141141 // O(log n) search + O(n) shift — far cheaper than rebuilding & sorting
142142 // the entire list from scratch on every alive-state transition.
143+ // Note: `<=` means new objects with the same StartTime are appended after
144+ // existing ones (stable insertion order within a tie group). The full
145+ // visual-tree Compare also applies CompareReverseChildID as a tie-breaker,
146+ // but AliveObjects consumers (e.g. cursor particles) don't require that
147+ // level of ordering stability.
143148 double startTime = drawable . HitObject . StartTime ;
144149 int lo = 0 , hi = aliveObjectsSortedCache . Count ;
145150
Original file line number Diff line number Diff line change @@ -257,6 +257,8 @@ protected override void LoadComplete()
257257 mods = Mods ? . ToArray ( ) ;
258258
259259 // Pre-filter once; avoids a per-frame `is IUpdatableByPlayfield` check on every mod.
260+ // Mods are resolved once at construction and don't change during gameplay, so this
261+ // cached slice is always valid for the lifetime of this Playfield.
260262 updatableByPlayfieldMods = mods ? . OfType < IUpdatableByPlayfield > ( ) . ToArray ( )
261263 ?? Array . Empty < IUpdatableByPlayfield > ( ) ;
262264
Original file line number Diff line number Diff line change @@ -64,6 +64,12 @@ public LocalisableString Text
6464 wholePart . Text = str [ ..dotIndex ] ;
6565 fractionPart . Text = str [ dotIndex ..pctIndex ] ;
6666 }
67+ else
68+ {
69+ // Fallback for unexpected format (e.g. localised strings without '.' or '%').
70+ wholePart . Text = str ;
71+ fractionPart . Text = string . Empty ;
72+ }
6773 }
6874 }
6975
You can’t perform that action at this time.
0 commit comments