GameServer: msgpack PopulateFireWeaponCommand drops isFiring — energy weapons can never START via MessagePack clients #912

Closed
opened 2026-08-05 13:12:32 +00:00 by spikerj · 2 comments
Owner

FireWeaponCommand.IsFiring (SpikerSoft.Common/Models/GameServer/CombatCommands.cs:106) is the start/stop switch for energy-weapon beams: ProcessFireWeaponCommandAsync (SpikerSoft.GameServer/Zones/SpaceZone.cs:2558) starts continuous fire when IsFiring == true and stops it when false.

But the MessagePack command parser never reads it — PopulateFireWeaponCommand (SpikerSoft.GameServer/Network/MessagePackSerializer.cs:1940) parses weaponId + directionX/Y/Z only, so IsFiring stays at its bool default false for every msgpack client. Result: over the msgpack path (Angular + Godot), FireWeapon on an energy weapon can only ever stop a beam that can never have been started.

The JSON path is unaffected (JsonPacketSerializer.cs:136 binds the whole command via GameServerJsonContext, including isFiring) — which is presumably why this was never noticed.

Fix: add to PopulateFireWeaponCommand:

if (TryGetValue(dict, "isFiring", out var f)) cmd.IsFiring = Convert.ToBoolean(f);

Found while reviewing spikersoft-games-godot PR #3, which adds a (future-use) fire_weapon(weaponId, isFiring, dir) client helper that sends the field correctly.

`FireWeaponCommand.IsFiring` (SpikerSoft.Common/Models/GameServer/CombatCommands.cs:106) is the start/stop switch for energy-weapon beams: `ProcessFireWeaponCommandAsync` (SpikerSoft.GameServer/Zones/SpaceZone.cs:2558) starts continuous fire when `IsFiring == true` and stops it when `false`. But the MessagePack command parser never reads it — `PopulateFireWeaponCommand` (SpikerSoft.GameServer/Network/MessagePackSerializer.cs:1940) parses `weaponId` + `directionX/Y/Z` only, so `IsFiring` stays at its `bool` default `false` for every msgpack client. Result: over the msgpack path (Angular + Godot), `FireWeapon` on an energy weapon can only ever *stop* a beam that can never have been started. The JSON path is unaffected (`JsonPacketSerializer.cs:136` binds the whole command via `GameServerJsonContext`, including `isFiring`) — which is presumably why this was never noticed. Fix: add to `PopulateFireWeaponCommand`: ```csharp if (TryGetValue(dict, "isFiring", out var f)) cmd.IsFiring = Convert.ToBoolean(f); ``` Found while reviewing spikersoft-games-godot PR #3, which adds a (future-use) `fire_weapon(weaponId, isFiring, dir)` client helper that sends the field correctly.
Author
Owner

Fix is ready in spikersoft-backend PR #517 (CI fully green): PopulateFireWeaponCommand now parses isFiring, with a DeserializeCommand_FireWeapon_MapsIsFiring regression test. Closing once the PR merges (merge is awaiting a human click — the agent's merge action was permission-blocked).

Fix is ready in spikersoft-backend PR #517 (CI fully green): `PopulateFireWeaponCommand` now parses `isFiring`, with a `DeserializeCommand_FireWeapon_MapsIsFiring` regression test. Closing once the PR merges (merge is awaiting a human click — the agent's merge action was permission-blocked).
Author
Owner

Resolved in spikersoft-backend PR #517 (merged to master). PopulateFireWeaponCommand now parses isFiring, so energy weapons can start firing via the MessagePack path; regression test added. Closing.

Resolved in spikersoft-backend PR #517 (merged to master). `PopulateFireWeaponCommand` now parses `isFiring`, so energy weapons can start firing via the MessagePack path; regression test added. Closing.
Sign in to join this conversation.