home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / enxle1f6 / src / games / battle / client / clientapplet / clientapplet.java < prev    next >
Encoding:
Java Source  |  1996-08-14  |  11.3 KB  |  497 lines

  1. /*
  2.  * @(#)ClientApplet.java
  3.  */
  4.  
  5. package games.Battle.client.ClientApplet;
  6.  
  7. import sun.applet.*;
  8. import win.ClosableFrame.*;
  9. import java.awt.*;
  10. import java.applet.*;
  11. import java.io.*;
  12. import java.net.*;
  13.  
  14. import games.Battle.shared.comm.*;
  15. import games.Battle.shared.sys.*;
  16. import games.Battle.client.EuropaClient.*;
  17.  
  18. /**
  19.  * This is the main applet for the game portion of the client.
  20.  * It organizes media resources and assembles a cohesively 
  21.  * executing client application to allow players to play
  22.  * the game against others.
  23.  *
  24.  * @author Alex Nicolaou
  25.  * @author Jay Steele
  26.  */
  27. public class ClientApplet extends Applet implements Runnable {
  28.  
  29.     /**
  30.      * A reference to this class's timeout agent.
  31.      */
  32.     ClientTimeoutAgent agent        = null;
  33.  
  34.     /**
  35.      * The game board graphic and event processing component.
  36.      */
  37.     ClientBoardComponent boardComp     = null;
  38.  
  39.     /**
  40.      * The game board containing the data for the client.
  41.      */
  42.     ClientBoard board                 = null;
  43.  
  44.     /**
  45.      * The runnable ressponsible for updating the display.
  46.      */
  47.     ClientUpdater updater            = null;
  48.  
  49.     /**
  50.      * The current "look" of the client.
  51.      */
  52.     ClientLook look                    = null;
  53.  
  54.     /**
  55.      * Flag to indicate when the main thread loop should terminate.
  56.      */
  57.     boolean gameOver                = false;
  58.  
  59.     /**
  60.      * The socket to the server.
  61.      */
  62.     Socket s                        = null;
  63.  
  64.     /**
  65.      *  The output stream to the server.
  66.      */
  67.     OutputStream os                    = null;
  68.  
  69.     /**
  70.      * The input stream from the server.
  71.      */
  72.     InputStream is                    = null;
  73.  
  74.     /**
  75.      * The container applet containing the game queues.
  76.      */
  77.     EuropaClient applet             = null;
  78.  
  79.     /**
  80.      * The server's ip address.
  81.      */
  82.     String serverIP;
  83.  
  84.     /**
  85.      * The server's port address.
  86.      */
  87.     int serverPort;
  88.  
  89.     /**
  90.      * A class containing information about the player.
  91.      */
  92.     PlayerInfo thisPlayer = null;
  93.  
  94.     /**
  95.      * The time it takes for an agent to time out.
  96.      */
  97.     static final int TIMEOUT = 60000*4;
  98.  
  99.     /**
  100.      * Default constructor. The ip address is set to the loopback
  101.      * ip and the port is set to 5000.
  102.      */
  103.     public ClientApplet() {
  104.         serverIP = "127.0.0.1";
  105.         serverPort = 5000;
  106.     }
  107.  
  108.     /**
  109.      * Data constructor. The server name and port are passed 
  110.      * here so a socket can be opened later. An instance of the
  111.      * calling applet is also passed in here for administration.
  112.      * @param applet the parent applet
  113.      * @param server the name of the machine running the server
  114.      * @param port the port the game server is listening to
  115.      * @see PlayerInfo
  116.      * @see EuropaClient
  117.      */
  118.     public ClientApplet(PlayerInfo p, EuropaClient applet, String server, int port) {
  119.         this.applet = applet;
  120.         serverIP = server;
  121.         serverPort = port;
  122.         thisPlayer = p;
  123.     }
  124.  
  125.     /**
  126.      * Initialize the game client by setting up the button bar,
  127.      * the client board and the board component which will process
  128.      * the graphic display and parsing of user events.
  129.      */
  130.     public void init() {
  131.  
  132.         board         = new ClientBoard();
  133.         boardComp     = new ClientBoardComponent(board);
  134.  
  135.         setLayout(new BorderLayout());
  136.  
  137.         // add buttons to the top of the panel
  138.         Panel buttons = new Panel();
  139.         buttons.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 2));
  140.         buttons.add(new Button("Quit"));
  141.         buttons.add(new Button("Surrender!"));
  142.  
  143.         if (thisPlayer.useSound()) {
  144.             buttons.add(new Button("Sound Off"));
  145.         }
  146.         else {
  147.             buttons.add(new Button("Sound On"));
  148.             ClientSounds.disableSounds();
  149.         }
  150.  
  151.         if (thisPlayer.useArcade()) {
  152.             buttons.add(new Button("XBattle Client"));
  153.         }
  154.         else {
  155.             buttons.add(new Button("Europa Client"));
  156.         }
  157.         add("North", buttons);
  158.  
  159.         add("Center", boardComp);
  160.         show();
  161.  
  162.     }
  163.  
  164.     /**
  165.      * Executed when the ClientApplet actually "starts". This method
  166.      * actually oversees the creating of the communication to the
  167.      * server and starts up the game.
  168.      */
  169.     public void start() {
  170.  
  171.         // first, start a thread which simply puts up a "please wait"
  172.         // message as the client sets itself up. The thread will be
  173.         // klled before the game play begins.
  174.         Thread pleaseWait = new Thread(new ClientCommLink(boardComp));
  175.         pleaseWait.start();
  176.  
  177.         // This is odd. I can't seem to rely on the ClientBoardComponent's
  178.         // offscreen image to be properly created until I make this 
  179.         // call here. Therefore, everything must wait until this point
  180.         // before attempting to draw, etc.
  181.         boardComp.repaint();
  182.         while (boardComp.getOffScreenImage() == null) {
  183.             try {
  184.                 Thread.sleep(100);
  185.             } 
  186.             catch (Exception e) {}
  187.         }
  188.  
  189.         // Now the offscreen should be properly built and things can
  190.         // move merrily along
  191.         if (thisPlayer.useArcade()) 
  192.             look = new ClientLookArcade(boardComp);
  193.         else 
  194.             look = new ClientLookTraditional(boardComp);
  195.  
  196.         updater        = new ClientUpdater(board, look);
  197.  
  198.         connectToServer();
  199.         setupGame();
  200.  
  201.         // kill our "please wait" thread since the game
  202.         // is about to begin
  203.         pleaseWait.stop();
  204.  
  205.         play();
  206.     }
  207.  
  208.     /**
  209.      * Called if a problem communicating with the server is 
  210.      * encountered. Throws up a dialog box allowing the user
  211.      * to tell the game to keep trying to talk to the server
  212.      * or to give up and kill the client.
  213.      */
  214.     public void handleCommunicationException() {
  215.  
  216.         // suspend the agent or else it will continue to give us
  217.         // timeout dialogs as we are thinking about dealing with this
  218.         // dialog.
  219.         if (agent != null) {
  220.             agent.suspend();
  221.         }
  222.  
  223.         Thread t = Thread.currentThread();
  224.         ClientAbortDialog dlg = new ClientAbortDialog(this, t);
  225.         // dlg.show();
  226.         dlg.toFront();
  227.  
  228.         // suspend this thread to emulate dlg as a modal dialog
  229.         // dlg will return control to us (thats why we pass the
  230.         // thread.
  231.         t.suspend(); 
  232.  
  233.         // when we get control back, restart and reset the timeout agent
  234.         if (agent != null) {
  235.             agent.resume();
  236.             agent.reset();
  237.         }
  238.     }
  239.  
  240.     /**
  241.      * Connect to the game server with the ip address and port
  242.      * we have been constructed with.
  243.      */
  244.     public void connectToServer() {
  245.  
  246.         agent = new ClientTimeoutAgent(60000*4, this);
  247.         agent.start();
  248.  
  249.         // open a socket to the server
  250.         try {
  251.             s = new Socket(serverIP, serverPort);
  252.         } catch ( IOException e ) {
  253.             handleCommunicationException();
  254.         }
  255.  
  256.         // bind an i/o stream
  257.         try {
  258.             os = s.getOutputStream();
  259.             is = s.getInputStream();
  260.         } catch ( IOException e ) {
  261.             handleCommunicationException();
  262.         }
  263.  
  264.         if (thisPlayer != null) {
  265.             try {
  266.                 thisPlayer.writeTo(os);
  267.             }
  268.             catch (IOException e) {
  269.                 handleCommunicationException();
  270.             }
  271.         }
  272.  
  273.         agent.stop();
  274.         agent = null;
  275.         boardComp.setOutputStream(os);
  276.     }
  277.  
  278.     /**
  279.      * Set up the game by reading "preliminary" information
  280.      * from the game server. This includes receiving a GameInit
  281.      * packet from the server (which contains game initialization
  282.      * information), and also receiving a TerrainInit packet
  283.      * from the server which gives a complete description of
  284.      * the terrain to the client.
  285.      * </p>
  286.      * A ClientTimeoutAgent is invoked at the beginning of this
  287.      * routine to monitor the time it takes to communicate
  288.      * with the server. If there are troubles connecting with
  289.      * the server, the agent will time out and give the user
  290.      * the options of trying to continue communication or to
  291.      * abort.
  292.      * @see GameInit
  293.      * @see TerrainInit
  294.      * @see ClientTimoutAgent
  295.      */
  296.     public void setupGame() {
  297.         agent = new ClientTimeoutAgent(TIMEOUT, this);
  298.         agent.start();
  299.  
  300.         GameInit ginit = new GameInit();
  301.         try {
  302.             ginit.readFrom(is);
  303.         } catch ( IOException e ) {
  304.             handleCommunicationException();
  305.         }
  306.         // The game init packet tells us which player we are. We must
  307.         // tell the board component which player we are so it can 
  308.         // handle events in an intelligent way
  309.         boardComp.setPlayer(ginit.getPlayer());
  310.         agent.reset();
  311.  
  312.         TerrainInit tinit = new TerrainInit(board);
  313.         try {
  314.             tinit.readFrom(is);
  315.         } catch ( IOException e ) {
  316.             handleCommunicationException();
  317.         }
  318.         look.updateTerrain(board);
  319.         agent.stop();
  320.         agent = null;
  321.     }
  322.  
  323.     /**
  324.      * Start the main game thread.
  325.      */
  326.     Thread clientThread;
  327.     public void play() {
  328.         clientThread = new Thread(this);
  329.         clientThread.start();
  330.     }
  331.  
  332.     /**
  333.      * The game thread body. This method fundamentally loops forever
  334.      * (until it is either a) killed by the player or b) kills itself
  335.      * via instructions from the server) and receives TurnDiffs from
  336.      * the server and instructs its ClientUpdater to wake up and
  337.      * redraw itself.
  338.      * </p>
  339.      * A ClientTimeoutAgent is reset at the beginning of each turn
  340.      * iteration. If a single turn takes too long communicating
  341.      * with the server the agent times out and allows the user
  342.      * to continue trying to communicate with the server or abort 
  343.      * the game.
  344.      * @see ClientTimeoutAgent
  345.      * @see TurnDiff
  346.      * @see ClientUpdater
  347.      */
  348.     public void run() {
  349.         agent = new ClientTimeoutAgent(TIMEOUT, this);
  350.         agent.start();
  351.         while (true) {
  352.             agent.reset();
  353.             TurnDiff turn = new TurnDiff(board, 0);
  354.             try {
  355.                 turn.readFrom(is);
  356.             } catch ( IOException e ) {
  357.                 handleCommunicationException();
  358.             }
  359.             if (turn.getTag() == TurnDiff.GAMEOVER) {
  360.  
  361.                 try {
  362.                     s.close();
  363.                     is.close();
  364.                     os.close();
  365.                 } catch ( Exception e ) {
  366.                     handleCommunicationException();
  367.                 }
  368.  
  369.                 agent.stop();
  370.                 agent = null;
  371.                 Component p = getParent();
  372.                 while (!(p instanceof Frame))
  373.                     p = p.getParent();
  374.                 ((Frame)p).dispose();
  375.                 return;
  376.             }
  377.             updater.update();
  378.         }
  379.     }
  380.  
  381.     /**
  382.      * Try to clean up everything that's going on in the game
  383.      * client when the client is being shut down.
  384.      */
  385.     public void destroy() {
  386.         // Command cmd = new Command(0, Symbols.SURRENDER, 0, 0, 0, 0);
  387.         try {
  388.             // cmd.writeTo(os);
  389.             clientThread.stop();
  390.             updater.stop();
  391.             agent.stop();
  392.             s.close();
  393.             is.close();
  394.             os.close();
  395.             clientThread.stop();
  396.         } catch ( Exception e ) {
  397.             // silently ignore problems
  398.         }
  399.         super.destroy();
  400.     }
  401.  
  402.     /**
  403.      * Handle events occuring in the ClientApplet, most notably button
  404.      * presses from the button bar.
  405.      * @param e the event to process
  406.      */
  407.     public boolean handleEvent(Event e) {
  408.  
  409.         if (e.arg == "Quit") {
  410.             destroy();
  411.             Component p = getParent();
  412.             while (!(p instanceof Frame))
  413.                 p = p.getParent();
  414.             ((Frame)p).dispose();
  415.         }
  416.  
  417.         else if (e.arg == "Surrender!") {
  418.             Button b = (Button)e.target;
  419.             b.disable();
  420.             Command cmd = new Command(0, Symbols.SURRENDER, 0, 0, 0, 0);
  421.             try {
  422.                 cmd.writeTo(os);
  423.                 boardComp.requestFocus();
  424.                 return true;
  425.             } catch ( Exception x ) {
  426.                 // where's the server?
  427.             }
  428.         }
  429.  
  430.         else if (e.arg == "Sound Off") {
  431.             Button b = (Button)e.target;
  432.             b.setLabel("Sound On");
  433.             ClientSounds.disableSounds();
  434.             boardComp.requestFocus();
  435.  
  436.             thisPlayer.setSound(false);
  437.             applet.setPlayerInfo(thisPlayer);
  438.  
  439.             return true;
  440.         }
  441.  
  442.         else if (e.arg == "Sound On") {
  443.             Button b = (Button)e.target;
  444.             b.setLabel("Sound Off");
  445.             ClientSounds.enableSounds();
  446.             boardComp.requestFocus();
  447.  
  448.             thisPlayer.setSound(true);
  449.             applet.setPlayerInfo(thisPlayer);
  450.  
  451.             return true;
  452.         }
  453.  
  454.         else if (e.arg == "XBattle Client") {
  455.             Button b = (Button)e.target;
  456.             b.setLabel("Europa Client");
  457.             look = new ClientLookTraditional(boardComp);
  458.             updater.setLook(look);
  459.             boardComp.requestFocus();
  460.  
  461.             thisPlayer.setArcade(false);
  462.             applet.setPlayerInfo(thisPlayer);
  463.  
  464.             return true;
  465.         }
  466.  
  467.         else if (e.arg == "Europa Client") {
  468.             Button b = (Button)e.target;
  469.             b.setLabel("XBattle Client");
  470.             look = new ClientLookArcade(boardComp);
  471.             updater.setLook(look);
  472.             boardComp.requestFocus();
  473.  
  474.             thisPlayer.setArcade(true);
  475.             applet.setPlayerInfo(thisPlayer);
  476.  
  477.             return true;
  478.         }
  479.         return false;
  480.     }
  481.  
  482.     public static void main(String argv[]) {
  483.         /*
  484.         Frame f = new ClosableFrame("Europa");
  485.         ClientApplet client = new ClientApplet();
  486.         client.init();
  487.         client.start();
  488.         f.add("Center", client);
  489.         f.pack();
  490.         client.start();
  491.         f.show();
  492.         */
  493.         AppletViewer.main(argv);
  494.     }
  495.  
  496. }
  497.