Ship Destruction on Crash
Overview
When a ship collides with a celestial body, it is permanently destroyed and removed from the player’s fleet. There is no respawn — the player must select or spawn a new ship.
Detection
Collision detection remains unchanged in physics service (simulation.py):
- After leapfrog integration, check if
dist_sq < body.radius * body.radius - Currently calls
respawn_after_collision()— this is replaced withdestroy_ship()
Destruction Flow
1. Physics Service
Replace respawn_after_collision(ship, body) with destroy_ship(ship, body):
- Remove ship from physics simulation (
self._shipsdict) - Delete ship hash from Redis:
DEL ship:{ship_id} - Remove from
active_shipsset - Publish
ship.destroyedevent togalaxy:shipsstream with:ship_id,player_id,body(crash site),reason: "collision"
Do NOT publish ship.crashed — replace it entirely with ship.destroyed.
2. Tick Engine
On ship.destroyed event (or on detecting missing ship data):
- Clear any active maneuver:
DEL maneuver:{ship_id} - Clear any automation rules referencing the ship
3. Players Service
Listen for ship.destroyed events on galaxy:ships stream:
- Remove ship from database:
DELETE FROM ships WHERE id = ? - Remove from fleet set:
SREM player:{player_id}:ships {ship_id} - If destroyed ship was the player’s active ship:
- Set active ship to another ship in fleet (if any)
- If no ships remain, set active_ship to null
- Publish
fleet.updatedevent so API gateway can notify the client
4. API Gateway
Handle ship.destroyed WebSocket event:
- Send to the owning player:
{type: "ship.destroyed", ship_id, ship_name, body, reason} - Send to all players:
{type: "ship.removed", ship_id}(removes from other players’ views)
5. Web Client
On receiving ship.destroyed:
- Show destruction notification: “Your ship [name] was destroyed at [body]”
- If it was the active ship:
- Switch to another ship in fleet if available
- If no ships remain, show spawn UI
- Remove ship from local state, 3D views, indicators
Edge Cases
- Docked ship: Should not be possible (docked ships don’t move), but guard against it
- NPC ship: Remove like any other ship; NPC rules may respawn a replacement
- Last ship destroyed: Player has empty fleet, must spawn fresh from fleet view
- Multiple simultaneous crashes: Each processed independently
Events
| Event | Stream | Payload |
|---|---|---|
ship.destroyed |
galaxy:ships |
ship_id, player_id, body, reason |
ship.removed |
(WebSocket) | ship_id (broadcast to all clients) |
fleet.updated |
galaxy:players |
player_id |