public void run() {
        buffer = "";

        try {
            Thread.sleep(1000);

            this.sendTelnetNegotiationParameters();

            // Ouput Welcome Message...
            try {
                File loginMsg = new File("./welcome.txt");
                String tmpStr;
                BufferedReader br = new BufferedReader(new FileReader(loginMsg));
                while ((tmpStr = br.readLine()) != null) {
                    sendText(tmpStr + "\r\n");
                }
            } catch (FileNotFoundException fnfe) {
                TrekLog.logError("Missing welcome screen text file - welcome.txt");
                sendText("Welcome to JTrek\r\n");
            } catch (IOException ioe) {
                TrekLog.logException(ioe);
            } finally {
                sendText("Active Players: " + TrekServer.getNumberOfActivePlayers() + "   Uptime: " + TrekServer.getUptime() + "\r\n");
                if (TrekServer.isTeamPlayEnabled()) {
                    sendText("[  TEAM GAME IN PROGRESS ]\r\n");
                }
            }

            // If the server is full...
            if (TrekServer.players.size() > 62) {
                TrekServer.clearDeadPlayerThreads();

                if (TrekServer.players.size() > 62) {
                    sendText("We're sorry.  The server is full.  Try again later.\r\n");
                    socket.close();
                    interrupt();
                    return;
                }
            }

            int clientInput;
            TrekLog.logMessage("Getting ship name.");

            do {
                // Reset the ship name.
                shipName = "";

                if (!doLogin()) {
                    TrekLog.logMessage("User disconnected.");
                    kill();
                    return;
                }

                if (dbInt.isShipPasswordProtected(shipName)) {
                    if (!doPassword()) {
                        TrekLog.logMessage("PASSWORD FAILURE: " + shipName + " failed password check.");
                    } else {
                        if (!dbInt.doesShipExist(shipName)) {
                            if (!doChooseShip()) {
                                TrekLog.logMessage("Failed getting ship class.");
                            } else {
                                ship.dbShipID = dbInt.getNewShipID(shipName);
                                timeShipLogin = Calendar.getInstance().getTimeInMillis();
                                dbConnectionID = dbInt.createNewConnection(this);
                            }
                        } else {
                            dbConnectionID = dbInt.createNewConnection(this);
                        }
                    }
                } else {
                    // new ship - establish which player it belongs to, and
                    // prompt for password confirmation before allowing them to
                    // select ship class
                    if (!doChoosePlayer()) {
                        TrekLog.logMessage("Failed to link new ship to player.");
                    } else {
                        if (!doChooseShip()) {
                            TrekLog.logMessage("Failed getting ship class.");
                        } else {
                            ship.dbShipID = dbInt.getNewShipID(shipName);
                            timeShipLogin = Calendar.getInstance().getTimeInMillis();
                            dbConnectionID = dbInt.createNewConnection(this);
                        }
                    }
                }

                if (state == WAIT_SOCKETTIMEDOUT) {
                    TrekLog.logMessage("Socket timeout. User disconnected.");
                    kill();
                    return;
                }

                if (state == WAIT_SOCKETERROR) {
                    TrekLog.logMessage("Socket error. User disconnected.");
                    kill();
                    return;
                }
            }
            while (state != WAIT_SUCCESSFULLOGIN);

            // Send the announcement message.
            long currentTime = Calendar.getInstance().getTimeInMillis();

            if ((ship.totalDamageGiven > 250000 || ship.gold > 50000) && (currentTime - ship.lastLogin) > 7200000)
                if (ship.dockTarget != null) {
                    TrekServer.sendAnnouncement(ship.dockTarget.name + ": " + getRankText(ship) + " " + ship.name + " has logged in.", true);
                }

            ship.lastLogin = currentTime;

            dbInt.updatePlayerLastLogin(this.dbPlayerID, ship.lastLogin);

            // check for player ban
            boolean isBanned = dbInt.isPlayerAccountLocked(dbPlayerID);

            // automatically assign to a team
            if ("acegikmoqsuwyACEGIKMOQSUWY".contains(ship.scanLetter)) {
                teamNumber = 1;
            } else {
                teamNumber = 2;
            }

            // if team play; zap them to the Nu quadrant near their base
            if (TrekServer.isTeamPlayEnabled()) {
                ship.currentQuadrant.removeShipByScanLetter(ship.scanLetter);
                ship.currentQuadrant = (TrekQuadrant) TrekServer.quadrants.get("Nu Quadrant");
                ship.currentQuadrant.addShip(ship);

                // put it near it's base
                Random gen = new Random();
                TrekObject baseObj = ship.currentQuadrant.getObjectByScanLetter(Integer.toString(teamNumber));
                ship.point = new Trek3DPoint(baseObj.point.x + (gen.nextInt() % 300), baseObj.point.y + (gen.nextInt() % 300),
                        baseObj.point.z + (gen.nextInt() % 300));
            }

            if (!isBanned) {
                // set anonymous flag
                isAnonymous = dbInt.isPlayerAnonymous(dbPlayerID);

                // Draw the initial hud.
                TrekLog.logMessage("Drawing initial HUD.");
                drawHud(true);

                TrekLog.logMessage("Ship " + shipName + " is now active.");

                state = WAIT_PLAYING;

                ship.currentQuadrant.addShip(ship);
            } else {
                TrekLog.logMessage("BANNED - attempted login of " + ship.name + " - playerID: " + dbPlayerID);
                state = WAIT_HSCLASS;
            }

            // check for possible multiship
            for (Enumeration e = TrekServer.players.elements(); e.hasMoreElements(); ) {
                TrekPlayer curPlayer = (TrekPlayer) e.nextElement();

                if (curPlayer == this) continue;
                if (curPlayer.state != WAIT_PLAYING) continue;  // in case they're sitting at a HS list, etc.
                if (curPlayer.ship instanceof ShipQ) continue;  // admin

                if (curPlayer.playerIP.equals(this.playerIP)) {
                    TrekLog.logMessage("--------------------    Possible Multi Report   --------------------");
                    String outputString = "*** Poss Multi: " + shipName + " from player " + dbPlayerID +
                            " and " + curPlayer.shipName + " from player " + curPlayer.dbPlayerID;
                    TrekLog.logMessage(outputString);
                    TrekServer.sendMsgToAdmins(outputString, ship.currentQuadrant.getObjectByScanLetter("1"), true, false);
                    TrekLog.logMessage("*** connectionIDs: " + dbConnectionID + " and " + curPlayer.dbConnectionID + ".");
                    TrekLog.logMessage("*** shipIDs: " + ship.dbShipID + " and " + curPlayer.ship.dbShipID + ".");
                    TrekLog.logMessage("*** current gold: " + ship.gold + " and " + curPlayer.ship.gold + ".");
                    TrekLog.logMessage("--------------------------------------------------------------------");
                }
            }

            while (state != WAIT_DEAD && state != WAIT_HSOVERALL && state != WAIT_HSCLASS) {
                try {
                    // Get the input from the client.
                    if (in.available() > 0) {
                        clientInput = in.read();
                        // If it is valid input.
                        if (clientInput != 0 && clientInput != 10) {
                            TrekLog.logDebug(shipName + ": Input received " + clientInput);
                            interpretCommand(clientInput);
                        }
                    } else { // If we received no input from the client.
                        try {
                            int timeoutInput = 0;
                            try {
                                // Attempt to read from the socket for a period of 10 milliseconds.
                                socket.setSoTimeout(10);
                                timeoutInput = in.read();
                                if (timeoutInput == -1) {
                                    TrekLog.logMessage(shipName + " closed the session.");
                                    kill();
                                    break;
                                }
                                if (state == WAIT_DEAD || state == WAIT_HSOVERALL || state == WAIT_HSCLASS) {
                                    break;
                                }
                                if (timeoutInput != 0 && timeoutInput != 10) {
                                    interpretCommand(timeoutInput);
                                }
                            } catch (SocketTimeoutException ste) {
                                /* Ignore */
                            } catch (InterruptedIOException iioe) { /* Ignore */
                            } catch (Exception e) {
                                TrekLog.logException(e);
                                kill();
                                break;
                            }
                            // If the input is -1, then the client disconnected without quiting the game.
                            if (timeoutInput == -1) {
                                TrekLog.logMessage(
                                        shipName + " closed the session.");
                                kill();
                                break;
                            }
                            // Otherwise sleep the thread so we don't take up processing time.
                            Thread.sleep(50);
                        } catch (InterruptedException ie) {
                            TrekLog.logMessage(
                                    this.getName() + ": Interrupted by server.");
                            if (!serverShutdown)
                                kill();
                            break;
                        } catch (Exception ue) {
                            kill();
                            TrekLog.logException(ue);
                            break;
                        }
                    }
                } catch (java.io.IOException ioe) {
                    TrekLog.logMessage(
                            this.getName() + ": Interrupted by server.");
                    if (!serverShutdown)
                        kill();
                    break;
                } catch (Exception oe) {
                    TrekLog.logException(oe);
                    kill();
                    break;
                }
            }

            input = "";

            if (state == WAIT_DEAD) {
                doBoom();
                ship.currentQuadrant.removeShipByScanLetter(ship.scanLetter);
                input = getBlockedInput(false, 60000, true);
            } else {
                if (ship != null)
                    ship.currentQuadrant.removeShipByScanLetter(ship.scanLetter);
            }

            timeShipLogout = Calendar.getInstance().getTimeInMillis();
            dbInt.updateConnection(this);

            if (state != TrekPlayer.WAIT_SOCKETERROR) {
                doHighScoresOverall();
                input = getBlockedInput(false, 60000, true);

                doHighScoresClass();
                input = getBlockedInput(false, 60000, true);

                doHighScoresFleet();
                input = getBlockedInput(false, 60000, true);

                sendText("\r\n");
            }

            TrekServer.removePlayer(this);

            TrekLog.logMessage("Player " + shipName + " thread exiting.");
        } catch (Exception e) {
            TrekLog.logException(e);
            kill();
        }
    }