This example should demonstrate the work of CORBA in the Swing based network game.The game was popular in student times of Audrius Meskauskas. After doing some web search we concluded that the game is called Five-in-a-row in English.
Introduction and rules
Five-in-a-row is a two player strategy game. The players are connected via network using CORBA-based RMI/IIOP protocol and make they moves with the help of the Swing-based interface. While playing, the users can also chat.
The system consists of the single server and any number of interconnected players. The person, willing to play, starts the client and connects the server. The server redirects call to the partner that has previously connected the same server, also willing to play.
The game desk is a field where it is possible to set O's and X'es, one per move. The goal is to get five O's in a row while preventing your partner from getting five X's in a row. Vertical, horizontal and diagonal rows are allowed. The system detects the loss-victory situation on the desk, but currently does not serve as a playing partner, requiring at least two human players for this game.
Both players can at any time reset the game (restarting it with the same player) or leave the game (disconnecting). The disconnected player can contact the game manager again, requesting to find another partner.
Simple as it is, the application has some features of the typical role playing game that frequently just has more states, actions, possible moves and also provides far richer graphics environment. The game manger serves as a World-Wide-Pub where you can always find a partner to play. The players can made both unsynchronized (chatting, game reset and leaving) and synchronized (moves) actions. The game state changes while playing, and the set of the available actions depends on the current state. Finally, the mouse and canvas are involved. However using RMI/IIOP machinery allowed to implement all this functionality with just 13 classes (plus 4 generated), all of them being rather simple.
The used IIOP protocol must ensure interoperability, allowing players to use different java virtual machines and operating systems. The processors may have the opposite byte order.
This example refers to the standard classes only and must be buildable from your IDE as long as it has any java 1.4 compiler.
Configuration and run
The game manager server executable class is gnu.classpath.examples.CORBA.swing.x5.X5Server . After start, it will print to console the Internet address that must be entered to the client to reach the manager.
The client executable class it gnu.classpath.examples.CORBA.swing.x5.Demo .
The game should run with GNU Classpath 0.19 and Sun Microsystems java 1.5.0_04. Due later fixed bugs it will not run with the older versions of these two implementations.
The game manager HTTP server uses port 1500. Hence all firewalls between the server and the player must be configured to allow HTTP on 1500. The ports, used by the RMI/IIOP are not persistent. GNU Classpath is configured to take ports 1501, 1502 and 1503 (the firewalls must allow to use them for RMI/IIOP). The CORBA implementation other than Classpath may use different port values. Unfortunately, there is no standard method to configure the used port range in a vendor-independent way.
The game server
The game manager is first reachable via http:// protocol (for instance http://123.456.7.89:1500). The simple server at this port always serves much longer string, representing the CORBA stringified object reference (IOR). The Five-in-a-row client uses this reference to find and access the remote game server object.
If the server player queue is empty, it simply queues this player. If the queue is not empty, the server introduces the arrived player and queued player to each other as leaves the them alone. When playing, the two clients communicate with each other directly, so the server is just a “meeting point” where the players can find each other. The game server is a console-only application.
The initial server http:// address must be transferred to players by some other means of communication (web chat, E-mail, link in a web site and so on). The server writes this address to the specified file, and the client can also take the default value from the same file. This is convenient when all applications run on a single machine, but also may be used to transfer the address via shared filesystem.
The game client
The clients are Swing-based GUI applications, capable for remote communication with each other and with the game manager. They have a set of predefined states and switch between these states in accordance to the preprogrammed logic. The client states are defined in the State interface. The README.html in the examples/gnu/classpath/examples/CORBA/swing/README.html also describes the possible client states. Each state has its own set of the available actions and each action either preserves the current state (chat, reset) or changes it following the rules. For this simple example, the state change rules are obvious.
The used RMI-IIOP architecture
Both player and game manager servants are derived from the org.omg.PortableServer.Servant and, being servants, are simply connected to the POA with POA.servant_to_reference . The first remote object (game manager) is found using the stringified object reference. No naming service is involved.
Where required, the CORBA objects are narrowed into required player and game manager interfaces using method PortableRemoteObject.narrow(org.omg.CORBA.Object object, Class interface_class) , passing the actual interface of the object as the second parameter. After narrowing, the remote side obtains possibility to invoke remote methods, defined in the interface of this object. After the first remote object is found, other objects can be simply passed as the method parameters. For instance, the game manager introduces another player by passing its reference as a parameter to the method Player.start_game.
The main executable class of the game client.
The main executable class of the game manager server
Other classes are described in README.html