Repository navigation
Conversation
The blaster, gauntlet, grenade launcher, lightning gun and dark matter gun have no view GUI, so the events rvWeapon posts on every shot and weapon switch were never delivered: the shared view model's queue grew for as long as one of them was in hand and was written into every save. The 256-event restore cap then rejected saves the same build had just written (themuffinator#192, "rvViewWeapon::Restore: invalid pending GUI event count 372"). UpdateGUI now drops queued events when the view model has no GUI to take them; the next weapon with a GUI posts its own weapon_init. A holstered weapon with a GUI still keeps its events for the raise. The restore bounds the count by the bytes left in the save, each event being at least its length, so existing saves carrying such a backlog load again while corrupt counts are still rejected. The write side and save layout are unchanged. weapon_gui_event_queue_contract.py checks both halves and SP/MP parity. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #192:
rvViewWeapon::Restore: invalid pending GUI event count 372makes a save impossible to load.Cause
rvWeaponposts named events (weapon_init,weapon_ammo,weapon_lower,weapon_raise, ...) to the shared view model on every shot and weapon switch, andrvWeapon::UpdateGUIhands them to the weapon's view GUI. The blaster, gauntlet, grenade launcher, lightning gun and dark matter gun have no view GUI (noguikey in their defs), soUpdateGUIreturned early and the queue was never drained. It kept growing for as long as one of those weapons was in hand, andrvViewWeapon::Savewrote all of it into every save. Since c2b4a7a the restore rejects more than 256 entries (MAX_SAVEGAME_GUI_EVENTS), so the same build refuses a save it has just written.Fix
UpdateGUIdrops queued events when the view model has no GUI to take them. Nothing could ever receive them, and the next weapon with a GUI posts its ownweapon_initandweapon_ammo. A holstered weapon with a GUI still keeps its events for the raise, as before.rvViewWeapon::Restorebounds the count by the bytes left in the save (each event is at least its 4-byte length), via a newidRestoreGame::RemainingBytes(), instead of the fixed cap. Existing saves carrying a backlog load again. Negative counts and counts the file cannot hold are still rejected, and each string is still length-checked byReadString.MAX_SAVEGAME_GUI_EVENTSis removed. SP and MP are identical.Verification (Linux x64, GCC 16, OpenGL)
Scripted on
game/airdefense2withdevmap,give allandopenq4_testInput: alternate between the grenade launcher and the blaster, firing each, for 70 rounds, then save.main(cbe967f2)rvViewWeapon::Restore: invalid pending GUI event count 996tools/tests/weapon_gui_event_queue_contract.py(wired into both workflows andopenq4_validate.py) checks the drop, the restore bound against a small model (372 and 996 accepted, negative and impossible counts rejected), the unchanged save writer and SP/MP parity. Reverting the drop makes it fail.savegame_corruption_contract.py,savegame_v3_contract.py,savegame_pointer_width_safety.pyandvalidation_hardening.pypass.Not verified: the reporter's own save (none attached), and a full playthrough. The reporter mentions it usually follows loading after a death. That fits the mechanism (any long stretch on a GUI-less weapon), but I haven't confirmed that specific sequence.
🤖 Generated with Claude Code