home *** CD-ROM | disk | FTP | other *** search
Java Source | 1996-08-14 | 11.3 KB | 497 lines |
- /*
- * @(#)ClientApplet.java
- */
-
- package games.Battle.client.ClientApplet;
-
- import sun.applet.*;
- import win.ClosableFrame.*;
- import java.awt.*;
- import java.applet.*;
- import java.io.*;
- import java.net.*;
-
- import games.Battle.shared.comm.*;
- import games.Battle.shared.sys.*;
- import games.Battle.client.EuropaClient.*;
-
- /**
- * This is the main applet for the game portion of the client.
- * It organizes media resources and assembles a cohesively
- * executing client application to allow players to play
- * the game against others.
- *
- * @author Alex Nicolaou
- * @author Jay Steele
- */
- public class ClientApplet extends Applet implements Runnable {
-
- /**
- * A reference to this class's timeout agent.
- */
- ClientTimeoutAgent agent = null;
-
- /**
- * The game board graphic and event processing component.
- */
- ClientBoardComponent boardComp = null;
-
- /**
- * The game board containing the data for the client.
- */
- ClientBoard board = null;
-
- /**
- * The runnable ressponsible for updating the display.
- */
- ClientUpdater updater = null;
-
- /**
- * The current "look" of the client.
- */
- ClientLook look = null;
-
- /**
- * Flag to indicate when the main thread loop should terminate.
- */
- boolean gameOver = false;
-
- /**
- * The socket to the server.
- */
- Socket s = null;
-
- /**
- * The output stream to the server.
- */
- OutputStream os = null;
-
- /**
- * The input stream from the server.
- */
- InputStream is = null;
-
- /**
- * The container applet containing the game queues.
- */
- EuropaClient applet = null;
-
- /**
- * The server's ip address.
- */
- String serverIP;
-
- /**
- * The server's port address.
- */
- int serverPort;
-
- /**
- * A class containing information about the player.
- */
- PlayerInfo thisPlayer = null;
-
- /**
- * The time it takes for an agent to time out.
- */
- static final int TIMEOUT = 60000*4;
-
- /**
- * Default constructor. The ip address is set to the loopback
- * ip and the port is set to 5000.
- */
- public ClientApplet() {
- serverIP = "127.0.0.1";
- serverPort = 5000;
- }
-
- /**
- * Data constructor. The server name and port are passed
- * here so a socket can be opened later. An instance of the
- * calling applet is also passed in here for administration.
- * @param applet the parent applet
- * @param server the name of the machine running the server
- * @param port the port the game server is listening to
- * @see PlayerInfo
- * @see EuropaClient
- */
- public ClientApplet(PlayerInfo p, EuropaClient applet, String server, int port) {
- this.applet = applet;
- serverIP = server;
- serverPort = port;
- thisPlayer = p;
- }
-
- /**
- * Initialize the game client by setting up the button bar,
- * the client board and the board component which will process
- * the graphic display and parsing of user events.
- */
- public void init() {
-
- board = new ClientBoard();
- boardComp = new ClientBoardComponent(board);
-
- setLayout(new BorderLayout());
-
- // add buttons to the top of the panel
- Panel buttons = new Panel();
- buttons.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 2));
- buttons.add(new Button("Quit"));
- buttons.add(new Button("Surrender!"));
-
- if (thisPlayer.useSound()) {
- buttons.add(new Button("Sound Off"));
- }
- else {
- buttons.add(new Button("Sound On"));
- ClientSounds.disableSounds();
- }
-
- if (thisPlayer.useArcade()) {
- buttons.add(new Button("XBattle Client"));
- }
- else {
- buttons.add(new Button("Europa Client"));
- }
- add("North", buttons);
-
- add("Center", boardComp);
- show();
-
- }
-
- /**
- * Executed when the ClientApplet actually "starts". This method
- * actually oversees the creating of the communication to the
- * server and starts up the game.
- */
- public void start() {
-
- // first, start a thread which simply puts up a "please wait"
- // message as the client sets itself up. The thread will be
- // klled before the game play begins.
- Thread pleaseWait = new Thread(new ClientCommLink(boardComp));
- pleaseWait.start();
-
- // This is odd. I can't seem to rely on the ClientBoardComponent's
- // offscreen image to be properly created until I make this
- // call here. Therefore, everything must wait until this point
- // before attempting to draw, etc.
- boardComp.repaint();
- while (boardComp.getOffScreenImage() == null) {
- try {
- Thread.sleep(100);
- }
- catch (Exception e) {}
- }
-
- // Now the offscreen should be properly built and things can
- // move merrily along
- if (thisPlayer.useArcade())
- look = new ClientLookArcade(boardComp);
- else
- look = new ClientLookTraditional(boardComp);
-
- updater = new ClientUpdater(board, look);
-
- connectToServer();
- setupGame();
-
- // kill our "please wait" thread since the game
- // is about to begin
- pleaseWait.stop();
-
- play();
- }
-
- /**
- * Called if a problem communicating with the server is
- * encountered. Throws up a dialog box allowing the user
- * to tell the game to keep trying to talk to the server
- * or to give up and kill the client.
- */
- public void handleCommunicationException() {
-
- // suspend the agent or else it will continue to give us
- // timeout dialogs as we are thinking about dealing with this
- // dialog.
- if (agent != null) {
- agent.suspend();
- }
-
- Thread t = Thread.currentThread();
- ClientAbortDialog dlg = new ClientAbortDialog(this, t);
- // dlg.show();
- dlg.toFront();
-
- // suspend this thread to emulate dlg as a modal dialog
- // dlg will return control to us (thats why we pass the
- // thread.
- t.suspend();
-
- // when we get control back, restart and reset the timeout agent
- if (agent != null) {
- agent.resume();
- agent.reset();
- }
- }
-
- /**
- * Connect to the game server with the ip address and port
- * we have been constructed with.
- */
- public void connectToServer() {
-
- agent = new ClientTimeoutAgent(60000*4, this);
- agent.start();
-
- // open a socket to the server
- try {
- s = new Socket(serverIP, serverPort);
- } catch ( IOException e ) {
- handleCommunicationException();
- }
-
- // bind an i/o stream
- try {
- os = s.getOutputStream();
- is = s.getInputStream();
- } catch ( IOException e ) {
- handleCommunicationException();
- }
-
- if (thisPlayer != null) {
- try {
- thisPlayer.writeTo(os);
- }
- catch (IOException e) {
- handleCommunicationException();
- }
- }
-
- agent.stop();
- agent = null;
- boardComp.setOutputStream(os);
- }
-
- /**
- * Set up the game by reading "preliminary" information
- * from the game server. This includes receiving a GameInit
- * packet from the server (which contains game initialization
- * information), and also receiving a TerrainInit packet
- * from the server which gives a complete description of
- * the terrain to the client.
- * </p>
- * A ClientTimeoutAgent is invoked at the beginning of this
- * routine to monitor the time it takes to communicate
- * with the server. If there are troubles connecting with
- * the server, the agent will time out and give the user
- * the options of trying to continue communication or to
- * abort.
- * @see GameInit
- * @see TerrainInit
- * @see ClientTimoutAgent
- */
- public void setupGame() {
- agent = new ClientTimeoutAgent(TIMEOUT, this);
- agent.start();
-
- GameInit ginit = new GameInit();
- try {
- ginit.readFrom(is);
- } catch ( IOException e ) {
- handleCommunicationException();
- }
- // The game init packet tells us which player we are. We must
- // tell the board component which player we are so it can
- // handle events in an intelligent way
- boardComp.setPlayer(ginit.getPlayer());
- agent.reset();
-
- TerrainInit tinit = new TerrainInit(board);
- try {
- tinit.readFrom(is);
- } catch ( IOException e ) {
- handleCommunicationException();
- }
- look.updateTerrain(board);
- agent.stop();
- agent = null;
- }
-
- /**
- * Start the main game thread.
- */
- Thread clientThread;
- public void play() {
- clientThread = new Thread(this);
- clientThread.start();
- }
-
- /**
- * The game thread body. This method fundamentally loops forever
- * (until it is either a) killed by the player or b) kills itself
- * via instructions from the server) and receives TurnDiffs from
- * the server and instructs its ClientUpdater to wake up and
- * redraw itself.
- * </p>
- * A ClientTimeoutAgent is reset at the beginning of each turn
- * iteration. If a single turn takes too long communicating
- * with the server the agent times out and allows the user
- * to continue trying to communicate with the server or abort
- * the game.
- * @see ClientTimeoutAgent
- * @see TurnDiff
- * @see ClientUpdater
- */
- public void run() {
- agent = new ClientTimeoutAgent(TIMEOUT, this);
- agent.start();
- while (true) {
- agent.reset();
- TurnDiff turn = new TurnDiff(board, 0);
- try {
- turn.readFrom(is);
- } catch ( IOException e ) {
- handleCommunicationException();
- }
- if (turn.getTag() == TurnDiff.GAMEOVER) {
-
- try {
- s.close();
- is.close();
- os.close();
- } catch ( Exception e ) {
- handleCommunicationException();
- }
-
- agent.stop();
- agent = null;
- Component p = getParent();
- while (!(p instanceof Frame))
- p = p.getParent();
- ((Frame)p).dispose();
- return;
- }
- updater.update();
- }
- }
-
- /**
- * Try to clean up everything that's going on in the game
- * client when the client is being shut down.
- */
- public void destroy() {
- // Command cmd = new Command(0, Symbols.SURRENDER, 0, 0, 0, 0);
- try {
- // cmd.writeTo(os);
- clientThread.stop();
- updater.stop();
- agent.stop();
- s.close();
- is.close();
- os.close();
- clientThread.stop();
- } catch ( Exception e ) {
- // silently ignore problems
- }
- super.destroy();
- }
-
- /**
- * Handle events occuring in the ClientApplet, most notably button
- * presses from the button bar.
- * @param e the event to process
- */
- public boolean handleEvent(Event e) {
-
- if (e.arg == "Quit") {
- destroy();
- Component p = getParent();
- while (!(p instanceof Frame))
- p = p.getParent();
- ((Frame)p).dispose();
- }
-
- else if (e.arg == "Surrender!") {
- Button b = (Button)e.target;
- b.disable();
- Command cmd = new Command(0, Symbols.SURRENDER, 0, 0, 0, 0);
- try {
- cmd.writeTo(os);
- boardComp.requestFocus();
- return true;
- } catch ( Exception x ) {
- // where's the server?
- }
- }
-
- else if (e.arg == "Sound Off") {
- Button b = (Button)e.target;
- b.setLabel("Sound On");
- ClientSounds.disableSounds();
- boardComp.requestFocus();
-
- thisPlayer.setSound(false);
- applet.setPlayerInfo(thisPlayer);
-
- return true;
- }
-
- else if (e.arg == "Sound On") {
- Button b = (Button)e.target;
- b.setLabel("Sound Off");
- ClientSounds.enableSounds();
- boardComp.requestFocus();
-
- thisPlayer.setSound(true);
- applet.setPlayerInfo(thisPlayer);
-
- return true;
- }
-
- else if (e.arg == "XBattle Client") {
- Button b = (Button)e.target;
- b.setLabel("Europa Client");
- look = new ClientLookTraditional(boardComp);
- updater.setLook(look);
- boardComp.requestFocus();
-
- thisPlayer.setArcade(false);
- applet.setPlayerInfo(thisPlayer);
-
- return true;
- }
-
- else if (e.arg == "Europa Client") {
- Button b = (Button)e.target;
- b.setLabel("XBattle Client");
- look = new ClientLookArcade(boardComp);
- updater.setLook(look);
- boardComp.requestFocus();
-
- thisPlayer.setArcade(true);
- applet.setPlayerInfo(thisPlayer);
-
- return true;
- }
- return false;
- }
-
- public static void main(String argv[]) {
- /*
- Frame f = new ClosableFrame("Europa");
- ClientApplet client = new ClientApplet();
- client.init();
- client.start();
- f.add("Center", client);
- f.pack();
- client.start();
- f.show();
- */
- AppletViewer.main(argv);
- }
-
- }
-