home *** CD-ROM | disk | FTP | other *** search
Java Source | 1996-08-14 | 16.3 KB | 755 lines |
- /*
- * @(#)EuropaClient.java
- */
- package games.Battle.client.EuropaClient;
-
- import java.applet.*;
- import java.awt.*;
- import java.net.*;
- import java.io.*;
-
- import win.ClosableFrame.*;
- import games.Battle.client.ClientApplet.*;
- import games.Battle.shared.sys.*;
- import games.Battle.shared.comm.*;
-
- /*
- * CommandPanel processes methods generated by button
- * presses from the buttons across the top of the Europa client
- * window. The buttons are added outside of this class,
- * we just handle the events here.
- *
- * @author Alex Nicolaou
- * @author Jay Steele
- */
- class CommandPanel extends Panel {
-
- /**
- * The game client applet.
- */
- EuropaClient client;
-
- /**
- * Construct a ComandPanel attached to the given EuropaClient applet.
- * @param client the EuropaClientApplet
- */
- public CommandPanel(EuropaClient client) {
- super();
- this.client = client;
- }
-
-
- /**
- * Process button presses.
- */
- public boolean handleEvent(Event e) {
- if (e.arg != null) {
- if (e.arg.equals("Quit")) {
- client.quit();
- }
- else if (e.arg.equals("Shutdown")) {
- client.shutdownServer();
- }
- else if (e.arg.equals("Change Info")) {
- client.changeInfo();
- }
- else if (e.arg.equals("Toggle Chat")) {
- client.toggleChatWindow();
- }
- }
- return super.handleEvent(e);
- }
- }
-
- /**
- * The Chat window for the Europa client. The Chat window consists
- * of a large multiline read-only text field which scrolls previous
- * messages upwards, and a small editable text field on the bottom
- * which allows the use to edit a message and send the message
- * to all of the other players by pressing the return key.
- * @author Alex Nicolaou
- * @author Jay Steele
- */
- class ChatWindow extends Frame {
-
- /**
- * The game client applet.
- */
- EuropaClient client;
-
- /**
- * The scrollable readonly area for display messages.
- */
- TextArea chatscreen;
-
- /**
- * The input field used to collect chat messaged from the user.
- */
- TextField input;
-
- /**
- * The maximum number of allowed buffered characters in the
- * scrollable chatscren.
- */
- static final int HISTORYLIMIT = 1024*8;
-
- /**
- * Construct the chat window by adding the large read-only text area
- * and a smaller editable text field on the bottom. We pass a
- * reference to the EuropaClient applet, who is responsible for
- * actually sending the message to the server and receiving
- * messages from the server.
- * @param client the EuropaClient applet from which we send/rcv messages
- */
- ChatWindow(EuropaClient client) {
- super("Chat Window");
- this.client = client;
-
- chatscreen = new TextArea();
- chatscreen.setEditable(false);
-
- add("Center", chatscreen);
-
- input = new TextField();
- add("South", input);
- }
-
-
- /**
- * Defines the minimum size of the frame.
- */
- public Dimension minimumSize() {
- return new Dimension(200, 100);
- }
-
-
- /**
- * Defines the preferred size of the frame.
- */
- public Dimension preferredSize() {
- return new Dimension(700, 400);
- }
-
-
- /**
- * Handle events in the chat window, primary the WINDOW_DESTROY
- * event (which instructs the parent applet to simply toggle
- * the chat window off), and a carriage return, which instructs
- * the EuropaClientApplet to send the message contained in the
- * text field to the server.
- * @param e the event to process
- */
- public boolean handleEvent(Event e) {
- if (e.id == Event.WINDOW_DESTROY) {
- client.toggleChatWindow();
- }
- else if (e.id == Event.KEY_RELEASE) {
- if ((char)e.key == '\n') {
- client.sendChat(input.getText());
- input.setText("");
- }
- }
-
- return super.handleEvent(e);
- }
-
-
- /**
- * Adds a message to the read-only area of the chat window, scrolling
- * all other messages up. If the size of the scrolled window buffer
- * reaches the maximum HISTORYLIMIT, the amount of scrolled text
- * is reduced by 1/2.
- * @param msg the message to add to the chat window
- */
- public void chatMsg(String msg) {
- chatscreen.appendText(msg + "\r\n");
- int numchars = chatscreen.getText().length();
- if (chatscreen.getText().length() > HISTORYLIMIT) {
- chatscreen.replaceText("", 0, HISTORYLIMIT/2);
- }
- }
- }
-
- /**
- * EuropaClient is the main applet for the "lobby" of the Europa
- * game. Sets up the game queue graphics, the who-list and the
- * chat window. This applet also initiates conversations with
- * the game server, logs users in, and spawns game board
- * clients when the server instructs it that a game is about to
- * begin.
- * @author Alex Nicolaou
- * @author Jay Steele
- */
- public class EuropaClient extends Applet implements Runnable {
-
- /**
- * 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 execution thread for this applet.
- */
- Thread appletThread = null;
-
- /**
- * The client container frame for this applet.
- */
- Frame clientFrame = null;
-
- /**
- * The game id, if a game is executing (-1 otherwise).
- */
- public int gameId = -1;
-
- /**
- * The container for the row of buttons at the top of the window.
- */
- Panel buttonBar;
-
- /**
- * The quit button.
- */
- Button quitButton;
-
- /**
- * The change info button.
- */
- Button infoButton;
-
- /**
- * The toggle chat window button.
- */
- Button chatButton;
-
- /**
- * The shutdown server button.
- */
- Button shutdownButton;
-
-
- /**
- * A component that displays the available games
- */
- QueuePanel gamePanel = null;
-
- /**
- * The chat window component.
- */
- ChatWindow chatWindow = null;
-
- /**
- * Construct an EuropaClient window, and set an internal reference
- * to an encapsulating frame.
- * @param f the frame window
- */
- public EuropaClient(Frame f) {
- clientFrame = f;
- }
-
-
- /**
- * Construct a EuropaClient instance free from the bonds of a
- * frame window.
- */
- public EuropaClient() {
- }
-
- String host;
- TextArea whoList;
-
- /**
- * Performs a list of inititialization routines, including contacting
- * the game server, and building all of the components which are
- * inside the EuropaClient (including the various game queues and
- * the who list)
- */
- public void init() {
- appletThread = Thread.currentThread();
-
- URL url = getDocumentBase();
-
- host = url.getHost();
-
- if (host.equals("")) {
- // we're running locally under the applet viewer; assume server
- // is local.
- host = "127.0.0.1";
- }
-
- int port = 5000;
-
- try {
- s = new Socket(host, port);
- } catch (Exception e) {
- Window err;
- err = new ErrorWindow(this, "Could not connect to "+host+":"+port);
- err.show();
- suspend();
- Common.exit(1);
- }
-
- // bind an i/o stream
- try {
- os = s.getOutputStream();
- is = s.getInputStream();
- } catch ( Exception e ) {
- Window err;
- err = new ErrorWindow(this,"Connection to "+host+":"+port+" lost.");
- err.show();
- suspend();
- Common.exit(1);
- }
-
- // read server banner
- InfoPacket banner = new InfoPacket();
- try {
- banner.readFrom(is);
- }
- catch (Exception e) {
- Window err;
- err = new ErrorWindow(this,"Connection to "+host+":"+port+" lost.");
- err.show();
- suspend();
- Common.exit(1);
- }
-
- if (clientFrame == null) {
- clientFrame = new ClosableFrame("Europa");
- getParent().remove(this);
- clientFrame.add("Center", this);
- }
-
- buttonBar = new CommandPanel(this);
- buttonBar.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 2));
- buttonBar.setBackground(Color.lightGray);
- quitButton = new Button("Quit");
- infoButton = new Button("Change Info");
- chatButton = new Button("Toggle Chat");
- shutdownButton = new Button("Shutdown");
- buttonBar.add(quitButton);
- buttonBar.add(infoButton);
- buttonBar.add(chatButton);
-
- whoList = new TextArea(30, 25);
- whoList.setEditable(false);
- whoList.setBackground(Color.black);
- whoList.setForeground(Color.yellow);
- whoList.setFont(new Font("Helvetica", Font.PLAIN, 12));
- clientFrame.add("East", whoList);
- clientFrame.add("North", buttonBar);
- gamePanel = new QueuePanel(16, this);
- clientFrame.add("Center", gamePanel);
-
- // load the media components
- ClientImages.loadAll(this);
- ClientSounds.loadAll(this);
- }
-
- PlayerInfo id = null;
-
- /**
- * Sends PlayerInfo information to the server so the server
- * can save the info for future reference.
- * @param r the PlayerInfo instance
- * @see PlayerInfo
- */
- public void setPlayerInfo(PlayerInfo r) {
- if (id == null) {
- id = r;
- }
- else {
- // send an update request
- try {
- ShellCommand cmd = new ShellCommand(ShellCommand.UPDATEID, 0);
- cmd.writeTo(os);
- id.setPassword(r.getPassword());
- id.setName(r.getName());
- id.setMail(r.getMail());
- id.writeTo(os);
- }
- catch (Exception e) {
- Window err;
- err = new ErrorWindow(this,"Connection lost.");
- err.show();
- suspend();
- Common.exit(1);
- }
- }
- }
-
-
- /**
- * Starts up the applet thread of execution. This includes:
- * a) trying to log into the game, b) registering this
- * player (based on their login id) with the server. If all is
- * successful, then the run() method is called to start the
- * game, otherwise the applet execution ends.
- */
- public void start() {
- appletThread = Thread.currentThread();
-
- // send a registration
- InfoPacket loginResult = new InfoPacket();
- int tries = 0;
- do {
- id = null;
- LoginWindow login = new LoginWindow(this);
- login.show();
- suspend();
-
- if (id == null) {
- Window err;
- err = new ErrorWindow(this, "Login cancelled. Exiting.");
- err.show();
- suspend();
- Common.exit(0);
- }
-
- try {
- id.writeTo(os);
- }
- catch (Exception e) {
- Window err;
- err = new ErrorWindow(this,"Connection lost.");
- System.out.println(e.toString());
- e.printStackTrace();
- err.show();
- suspend();
- Common.exit(1);
- }
-
- try {
- loginResult.readFrom(is);
- }
- catch (Exception e) {
- Window err;
- err = new ErrorWindow(this,"Connection lost.");
- System.out.println(e.toString());
- e.printStackTrace();
- err.show();
- suspend();
- Common.exit(1);
- }
-
- if (loginResult.isFatal()) {
- Window err;
- err = new ErrorWindow(this, loginResult.toString());
- err.show();
- suspend();
- }
- tries++;
- } while (loginResult.isFatal() && tries < 3);
-
- if (loginResult.isFatal()) {
- Common.exit(0);
- }
-
- // read in all the info on this user
- try {
- id.readFrom(is);
- }
- catch (Exception e) {
- Window err;
- err = new ErrorWindow(this,"Connection lost.");
- System.out.println(e.toString());
- e.printStackTrace();
- err.show();
- suspend();
- Common.exit(1);
- }
-
- if (id.isWizard())
- buttonBar.add(shutdownButton);
-
- setLayout(new BorderLayout());
-
- clientFrame.setBackground(Color.orange);
- clientFrame.pack();
- clientFrame.show();
-
- run();
- }
-
-
- /**
- * Overloaded stop method to do nothing.
- */
- public void stop() {
- }
-
- /**
- * Read all of the game information from the server, and use
- * the information to properly update the contents of the game
- * queue window. This method is also responsible for
- * recognizing when a game queue has been successfull filled
- * and starting the game clients.
- * @param numGames the number of games to read from the server
- */
- public void readGames(int numGames) throws java.io.IOException {
- boolean getGoing = false;
-
- while (numGames-- > 0) {
- GameInfo game = new GameInfo();
- game.readFrom(is);
-
- gamePanel.setGameInfo(game);
- if (gameId == game.getId() && game.isRunning()) {
- getGoing = true;
- }
- }
-
- //clientFrame.removeAll();
- //clientFrame.add("Center", gamePanel);
- //clientFrame.add("East", whoList);
- //clientFrame.add("North", buttonBar);
-
- clientFrame.pack();
-
- if (getGoing) {
- // time to actually start the game
- ClientApplet client;
- client = new ClientApplet(id, this, host, 5100+gameId);
- Frame f = new ClientFrame("Europa Control", client);
-
- client.init();
- f.add("Center", client);
- f.pack();
- f.show();
-
- client.start();
- f.pack();
-
- // make sure we never start two clients for the same game
- gameId = -1;
- }
- }
-
-
- /**
- * Read numplayers WhoInfo packets from the server and
- * display them in the who list.
- * @param numplayers the number of players to read
- */
- public void readWho(int numplayers) throws java.io.IOException {
- whoList.setText("Handle\t\tRating\tName/Email\r\n");
- while (numplayers-- > 0) {
- WhoInfo p = new WhoInfo();
- p.readFrom(is);
- whoList.appendText(p.toString() + "\r\n");
- }
- }
-
-
- /**
- * Read numlines of chat window messages from the server and
- * display them in the chat window (if the chat window exists).
- * @param numlines the number of lines to read
- */
- public void readChat(int numlines) throws java.io.IOException {
- while (numlines-- > 0) {
- InfoPacket p = new InfoPacket();
- p.readFrom(is);
- if (chatWindow != null)
- chatWindow.chatMsg(p.toString());
- }
- }
-
-
- /**
- * The main execution loop for this applet's thread. The thread
- * basically waits for input from the server and updates the
- * contents of all of the info window when information is
- * received.
- */
- public void run() {
- try {
- ShellCommand type = new ShellCommand();
- CountPacket count = new CountPacket();
-
- while (true) {
- try {
- type.readFrom(is);
- count.readFrom(is);
-
- if (type.getCommand() == ShellCommand.GAMES) {
- readGames(count.getCount());
- }
- else if (type.getCommand() == ShellCommand.WHO) {
- readWho(count.getCount());
- }
- else if (type.getCommand() == ShellCommand.CHATMSG) {
- readChat(count.getCount());
- }
- }
- catch (java.io.EOFException e) {
- System.out.println("Exception: "+e);
- System.out.println("Server must have disappeared. Stop");
- return;
- }
- catch (Exception e) {
- System.out.println("Ignoring Exception: "+e);
- e.printStackTrace();
- }
- }
- }
- catch (Exception e) {
- System.out.println("Exception: "+e);
- e.printStackTrace();
- }
- }
-
-
- /**
- * Sends a request to the server to join the given game.
- * @param game the game to join
- */
- public void join(int game) throws java.io.IOException {
- if (gameId > -1) {
- ShellCommand cmd = new ShellCommand(ShellCommand.QUIT, gameId);
- cmd.writeTo(os);
- }
- if (game != gameId) {
- gameId = game;
- ShellCommand cmd = new ShellCommand(ShellCommand.JOIN, gameId);
- cmd.writeTo(os);
- }
- else
- gameId = -1;
- }
-
-
- /**
- * Return the currently executing game Id, -1 if there is no
- * game in progress.
- */
- public int getGameId() {
- return gameId;
- }
-
-
- /**
- * Suspends this applet's main thread.
- */
- public void suspend() {
- appletThread.suspend();
- }
-
-
- /**
- * Resumes this applet's main thread.
- */
- public void resume() {
- appletThread.resume();
- }
-
-
- /**
- * Quits this applet, cleaning up any lingering windows and
- * informing the server that we are quitting.
- */
- public void quit() {
- if (chatWindow != null) {
- chatWindow.dispose();
- chatWindow = null;
- }
- try {
- ShellCommand cmd = new ShellCommand(ShellCommand.DISCONNECT, 0);
- cmd.writeTo(os);
- }
- catch (Exception e) {}
-
- clientFrame.dispose();
- Common.exit(0);
- }
-
-
- /**
- * Sends a message to the server to shut itself down. This method
- * is really only accessible by wizards from their display consoles.
- */
- public void shutdownServer() {
- try {
- ShellCommand cmd = new ShellCommand(ShellCommand.SHUTDOWN, 0);
- cmd.writeTo(os);
- }
- catch (Exception e) {}
-
- quit();
- }
-
-
- /**
- * Creates a dialog box allowing the user to change his or her
- * user information.
- */
- public void changeInfo() {
- LoginWindow login = new LoginWindow(this, id);
- login.show();
- suspend();
- }
-
-
- /**
- * Turns the chat window on if it is off, and off if
- * it is on.
- */
- public void toggleChatWindow() {
- if (chatWindow == null) {
- chatWindow = new ChatWindow(this);
- chatWindow.pack();
- chatWindow.show();
- }
- else {
- chatWindow.dispose();
- chatWindow = null;
- }
- }
-
-
- /**
- * Sends the given chat message to the server.
- * @param msg the message to send to the server
- */
- public void sendChat(String msg) {
- try {
- ShellCommand cmd = new ShellCommand(ShellCommand.CHATMSG, 0);
- cmd.writeTo(os);
- InfoPacket info = new InfoPacket(msg, InfoPacket.Info);
- info.writeTo(os);
- }
- catch (Exception e) {
- Window err;
- err = new ErrorWindow(this,"Connection lost.");
- System.out.println(e.toString());
- e.printStackTrace();
- err.show();
- suspend();
- Common.exit(1);
- }
- }
-
-
- /**
- * The main routine for an applet-less execution.
- */
- public static void main(String argv[]) {
- Frame f = new ClosableFrame("Europa");
- EuropaClient client = new EuropaClient(f);
- client.init();
- f.add("Center", client);
- client.start();
- }
-
- }
-