The server is initially invoked through the main() in nooga.server.NOOGAServerImpl.java. When the main function is invoked, the server starts itself up, registers itself in the rmiregistry (which must be already running on the server's machine), and waits for players to connect to it through RMI functions.
After a player has connected to the server and is ready to play, the player is placed on a list specific to players wishing to play that specific game (in NOOGAWaiters.java). When enough players are ready to play a specific game, (or if enough players have been waiting long enough for a game), the NOOGAServerImpl will spin off that game's GameHandler to start and play the game with those players. The NOOGAServerImpl has nothing more to do with those players or that game handler ever again.
The NOOGAServerImpl is ONLY concerned with processing players who are waiting to begin a game.
-NOOGAGameHandler and it subclasses (right now:
DotsGameHandler and JoggleGameHandler)
The GameHandler is what actually "plays" the game. It controls the flow of execution for playing the specific game. It communicates through RMI with the NOOGAClientImpl's associated with each of the players playing the game.
When the GameHandler is instantiated, it places itself in the rmiregistry. Then, it passes a String to all the clients, letting them know where in the rmiregistry the GameHandler can be found. The clients then lookup the GameHandler, and two-way communication is now established.
From here, the GameHandler "talks" to the players in its game (via their NOOGAClientImpl's), calling functions and having various functions of itself called by the clients. The correct sequencing for this interaction is determined by the specific GameHandler for each game.
Remote players (XML, Simple String):
When the NOOGAServerImpl is started up, the NOOGASocketListener
must be started up as well, if remote connections via sockets (as opposed
to RMI) are to be supported. The NOOGASocketListener listens on
a socket for a player to connect. When a player connects wanting
to play a game, the NOOGASocketListener spins off a thread to handle them.
First, it determines which type of game the player wishes to play, and which protocol it will use (i.e. XML or Simple String). After doing so, it creates the appropriate "Fake Front End" (NOOGAFE). This front end will encode all calls it receives into the appropriate protocol. Then, it will send the data (as a String) across the socket to the "real" player. After that, it is up to the "real" player to process the data appropriately. This "Fake Front End" will also receive and process any information being passed through the socket by the "real" player. (Then passing this information to its NOOGAClientImpl, which then, using RMI, passes it to the GameHandler.)
Once the "Fake Front End" is created, a NOOGAClientImpl is created with the "Fake Front End" as a private variable. The NOOGAClientImpl gets the NOOGAServerImpl out of the rmiregistry, and tells the Server that it is waiting to play the game. Once the GameHandler has been created, and the NOOGAClientImpl starts receiving calls, it simply forwards them to its "Fake Front End." This "Fake Front end" then stuffs the information over the socket, according whatever protocol it (and the user) is using. The "real" player then takes the data and processes it whatever way necessary. Any data the "real" player sends back will go through the socket to the "Fake Front End" listening to that socket. The "Fake Front End" will decode the information according to the protocol it is using, and send it to its NOOGAClientImpl, which will in turn send the information to the GameHandler using RMI.
RMI players use a lot of the same setup process as
outlined above. However, nothing is passed over sockets, and no "Fake
Front End" is necessary!
When a person using RMI wants to connect, they must write a NOOGAFE specific to the game they wish to play, and a program that constructs a that NOOGAFE. Then, they make an instance of NOOGAConnector and pass it this front end. Much like the NOOGASocketListener outlined above, the NOOGAConnector creates a NOOGAClientImpl which takes the Front End as a parameter. The NOOGAClientImpl tells the server that it has a player ready to play. Then, once the GameHandler has been spun off, it sends all its commands to this NOOGAClientImpl, which are then forwarded to the game-specific NOOGAFE. If information must travel from the player to the GameHandler, it originates in the NOOGAFE. It is then passed to its NOOGAClientImpl, and using RMI, it invokes one of the GameHandler's functions.
NOTE: What used to be called NOOGAccess is now called NOOGAConnector.