Space game: pressing C (cloak) crashes the render loop when the shield bubble is active #919

Closed
opened 2026-08-05 19:05:29 +00:00 by spikerj · 0 comments
Owner

Repro: In the space game, press `c` (Toggle Stealth) while flying the local ship. The game freezes; console shows `TypeError: Cannot set properties of undefined (setting 'value')`.

Root cause (client-side, spikersoft-angular):

  • The local ship's shield bubble mesh is attached as a child of `localShip` (`space-game.component.ts:4547-4548`, jitter fix).
  • `applyCloakShader()` (`space-game.component.ts:4972`) traverses `localShip` and swaps every mesh's material to the cloak `ghostMaterial` — including the shield bubble.
  • Next frame, `ShieldEffectManager.updatePassiveBubbles()` (`effects/shield-effect.ts:441-450`) reads the material back off the bubble mesh. Its `if (material.uniforms)` guard passes (ghost material is a ShaderMaterial with `uTime`/`uCameraPos`), then `material.uniforms.time.value = ...` throws — `time` doesn't exist on the ghost material. The exception kills the rAF loop → game frozen.
  • Same landmine in `setShieldActive` (`shield-effect.ts:326-329`, `uniforms.opacity`) if a shield state change arrives while cloaked.

Mechanism confirmed with a standalone three.js repro (exact TypeError). Backend `ToggleStealth` path and Godot client verified fine; GameServer logs show no server-side errors (recent task restarts were deploy kills, exit 137).

Fix: skip the shield bubble in the cloak material swap (tag it via `userData`), and tighten the uniform guards in `shield-effect.ts` so a foreign material can never take down the render loop.

**Repro:** In the space game, press \`c\` (Toggle Stealth) while flying the local ship. The game freezes; console shows \`TypeError: Cannot set properties of undefined (setting 'value')\`. **Root cause (client-side, spikersoft-angular):** - The local ship's shield bubble mesh is attached as a **child of \`localShip\`** (\`space-game.component.ts:4547-4548\`, jitter fix). - \`applyCloakShader()\` (\`space-game.component.ts:4972\`) traverses \`localShip\` and swaps **every** mesh's material to the cloak \`ghostMaterial\` — including the shield bubble. - Next frame, \`ShieldEffectManager.updatePassiveBubbles()\` (\`effects/shield-effect.ts:441-450\`) reads the material back off the bubble mesh. Its \`if (material.uniforms)\` guard passes (ghost material is a ShaderMaterial with \`uTime\`/\`uCameraPos\`), then \`material.uniforms.time.value = ...\` throws — \`time\` doesn't exist on the ghost material. The exception kills the rAF loop → game frozen. - Same landmine in \`setShieldActive\` (\`shield-effect.ts:326-329\`, \`uniforms.opacity\`) if a shield state change arrives while cloaked. Mechanism confirmed with a standalone three.js repro (exact TypeError). Backend \`ToggleStealth\` path and Godot client verified fine; GameServer logs show no server-side errors (recent task restarts were deploy kills, exit 137). **Fix:** skip the shield bubble in the cloak material swap (tag it via \`userData\`), and tighten the uniform guards in \`shield-effect.ts\` so a foreign material can never take down the render loop.
Sign in to join this conversation.