I am trying to design a game which needs to do the following: Have a lobby period, move players into a pre-game setup, start the game, end the game, repeat.
My current setup is as follows: A MatchManager creates and destroys Match objects and sets it's state when needed. There is a MatchState enum (No lobby period) where players skip the lobby and go directly from the game ending to the pregame of the next. We would like to now add a Lobby period as described.
In a previous version of the game, we had a Lobby object with a queue of players inside of it. Then we simply had 2 fields inside MatchManager: current match and current lobby. Using a lot of painful null checks, we were able to tell whether or not the game was in lobby period. We do not like this solution, and wonder if there is a better one.
What I am wondering is, what is a good way to manage a Lobby without adding it to MatchState (since MatchState should only be responsible for the LifeCycle of a Match) and also not creating one global GameState (this game is intended to be very flexible, so it's likely at some point we will be running multiple matches at once. This requires some kind of MatchState, and it would be very confusing to manage 2 states at once). Additionally, is there an alternative to using enums for a "MatchState" all together? One of our main goals was to create a Core game engine in which we can easily add/remove states in the future without destroying the lifecycle of some code.
Edit: additionally, we don't want to directly add Lobby into the core (since our core may be used in a game that doesn't need a lobby). I just wanted to stress this, since it means we are looking for a different kind of solution (dynamic states).