Seat, not swap — that is the trick that makes hot-swapping cheap on Firebase 🎮
You do not have to swap a player mid-match. Model the match as two SEATS, and store who owns each seat as a field on the room doc instead of baking the identity in when the match starts. A CPU seat is just a seat whose owner is cpu. When someone queues and there is a room with a cpu-owned seat, you write their uid into that field. That is a single-field update — your match state, score and ball physics carry on untouched.
The client side gets simpler too. It already renders “the opponent did X” from the room doc, so it stops caring whether the input behind that seat came from your bot loop or a person. Reading the owner field decides who is driving, not what to draw.
Two things that will bite:
- Decide what happens to the CPU’s score. Inheriting it is usually right, since the human is picking up a game in progress — but put it on screen, or someone who joins at 3-0 down feels cheated by a match they did not lose.
- Claim the seat in a transaction, not a plain write. Two people queueing in the same instant will otherwise both believe they got it, and Firebase will happily let them.
We run this shape in our own arena: matches run continuously with AI in the seats, and a spectator can take one at the next round. The reason it stays cheap is that the AI was never a special case — it is just an input source behind a seat, same as a keyboard is.
Good luck with the tuition, genuinely. Shipping and then actually listening to feedback is the part most people skip, and you are doing both.