Behaves Exactly as Before

Written later and filed to this date, as part of filling in every day of the year.

What happened. My survivor shooter streams a world in rooms, and when the ship leaves a room, a sweep clears the loose loot it left behind. A room can also place a reward: a cache of field boosts, a chest, a field of crates, spawned into a slot the room owns. For a while the sweep could not tell a placed reward from loose loot, so a cache the player flew past was deleted on the way out and never came back, because the slot still counted as stocked. A feature fixed that: placed rewards are exempt from the sweep, an untouched slot is put away with its room and restocked on return, and a partly looted slot is left alone, since re-arming it would pay twice. The registry of which objects belong to which slot lived in memory. Its commit says so, and says what that means: after a refresh restores the run, the registry is empty, the run retires no slot, and behaves exactly as before.

When it was noticed. One minute later, in the backlog entry that closed the item, written by the same session, which filed the restore blindness as a chosen degradation with its own ticket. Sixteen minutes after that, the same session un-chose it. The fix commit is the one that says the quiet part: a restored field-boost cache was worse than lost, it was re-armed for deletion.

The cause. “Exactly as before” was accurate, and before included the defect. With the registry empty after a restore, the set of protected entities was empty too, so the sweep ran over the restored pickups exactly as it had before the feature existed and destroyed both on the next room exit. The crates had it worse: the serializer skips every destructible as transient, so a restored run had no crates at all, while the slot id was already in the list of stocked slots, so nothing would ever place them again. The sentence that sounded like a safe fallback described the feature switching itself off at the first refresh, in a game that restores from a save whenever the phone rotates.

The fix. The save now carries, for each stocked slot, its still-alive objects at their live positions and an intact flag. On restore, after the passes that recreate entities and chests, chests and boosts are linked back to the handles those passes already made, and crates are spawned again, because nothing else creates them. A slot restored as not intact is treated as partly looted: protected from the sweep and never retired. The field is optional and additive, on an expedition-only block, so the save version did not move and a legacy save restores no slot record.

What guards it now. The record itself: the thing a refresh used to forget is written where a refresh reads. And a rule I now apply to any commit body that promises a restored run behaves as before. Before what, exactly. If the answer is before the fix, the sentence is describing the bug.


← all writing