package org.pokenet.server; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; import java.util.Scanner; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPasswordField; import javax.swing.JTextField; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.pokenet.server.network.TcpProtocolHandler; /** * Represents a game server. * * Starting a server requires a parameter to be passed in, i.e. java GameServer -s low -p 500 * Here are the different settings: * -low * < 1.86ghz * < 256MB Ram * < 1mbps Up/Down Connection * 75 Players * -medium * < 2ghz * 512MB - 1GB Ram * 1mbps Up/Down Connection * 200 Players * -high * > 1.86ghz * > 1GB Ram * > 1mbps Up/Down Connection * > 500 Players * * @author shadowkanji * @author Nushio * */ public class GameServer { private static GameServer m_instance; private static final long serialVersionUID = 1L; private static ServiceManager m_serviceManager; private static int m_maxPlayers, m_movementThreads; private static String m_dbServer, m_dbName, m_dbUsername, m_dbPassword, m_serverName; private static boolean m_boolGui; private JTextField m_dbS, m_dbN, m_dbU, m_name; private JPasswordField m_dbP; private JButton m_start, m_stop, m_set, m_exit; private int m_highest; private JLabel m_pAmount, m_pHighest; private JFrame m_gui; /* The revision of the game server */ // would be more helpful if this was the SVN version.. so it auto updated public static int REVISION = getSVNRev();//1786; /** * Load pre-existing settings if any * NOTE: It loads the database password if available. * Password is line after serverName */ private void loadSettings(){ File foo = new File("res/settings.txt"); if(foo.exists()) { try { Scanner s = new Scanner(foo); m_dbServer = s.nextLine(); m_dbName = s.nextLine(); m_dbUsername = s.nextLine(); m_serverName = s.nextLine(); m_dbPassword = s.nextLine(); s.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * .Gets the SVN revision for the server * * @return the value on the third line of .svn/entries */ private static int getSVNRev() { int rev = 0; boolean foundRevision = false; try { BufferedReader input = new BufferedReader(new FileReader(".svn/entries")); try { String line = null; while (( line = input.readLine()) != null && !foundRevision){ if(line.equals("dir")){ rev = Integer.parseInt(input.readLine()); // this hopefully is the revision number foundRevision = true; } } } finally { input.close(); } } catch (IOException ex){ ex.printStackTrace(); // probably no svn file... oh well. rev = 1868; } return rev; } /** * Asks for Database User/Pass, then asks to save * NOTE: It doesnt save the database password */ private void getConsoleSettings(){ ConsoleReader r = new ConsoleReader(); System.out.println("Please enter the required information."); System.out.println("Database Server: "); m_dbServer = r.readToken(); System.out.println("Database Name:"); m_dbName = r.readToken(); System.out.println("Database Username:"); m_dbUsername = r.readToken(); System.out.println("Database Password:"); m_dbPassword = r.readToken(); System.out.println("This server's IP or hostname:"); m_serverName = r.readToken(); System.out.println("Save info? (y/N)"); String answer = r.readToken(); if(answer.contains("y")||answer.contains("Y")){ saveSettings(); } System.out.println(); System.err.println("WARNING: When using -nogui, the server should only be shut down using a master client"); } /** * Default constructor */ public GameServer(boolean autorun) { m_instance = this; if(autorun){ loadSettings(); start(); }else{ if(m_boolGui) { loadSettings(); createGui(); } else { ConsoleReader r = new ConsoleReader(); System.out.println("Load Settings? y/N"); String answer = r.readToken(); if(answer.contains("y")||answer.contains("Y")){ loadSettings(); }else{ getConsoleSettings(); } start(); } } } /** * Generates the gui-version of the server */ private void createGui() { m_gui = new JFrame(); m_gui.setTitle("Pokenet Server"); m_gui.setSize(148, 340); m_gui.setDefaultCloseOperation(0); //DO_NOTHING_ON_CLOSE m_gui.getContentPane().setLayout(null); m_gui.setResizable(false); m_gui.setLocation(32, 32); /* * Set up the buttons */ m_pAmount = new JLabel("0 players online"); m_pAmount.setSize(160, 16); m_pAmount.setLocation(4, 4); m_pAmount.setVisible(true); m_gui.getContentPane().add(m_pAmount); m_pHighest = new JLabel("[No record]"); m_pHighest.setSize(160, 16); m_pHighest.setLocation(4, 24); m_pHighest.setVisible(true); m_gui.getContentPane().add(m_pHighest); m_start = new JButton("Start Server"); m_start.setSize(128, 24); m_start.setLocation(4, 48); m_start.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { start(); } }); m_gui.getContentPane().add(m_start); m_stop = new JButton("Stop Server"); m_stop.setSize(128, 24); m_stop.setLocation(4, 74); m_stop.setEnabled(false); m_stop.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { stop(); } }); m_gui.getContentPane().add(m_stop); m_set = new JButton("Save Settings"); m_set.setSize(128, 24); m_set.setLocation(4, 100); m_set.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { saveSettings(); } }); m_gui.getContentPane().add(m_set); m_exit = new JButton("Quit"); m_exit.setSize(128, 24); m_exit.setLocation(4, 290); m_exit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { exit(); } }); m_gui.getContentPane().add(m_exit); /* * Settings text boxes */ m_dbS = new JTextField(); m_dbS.setSize(128, 24); m_dbS.setText("MySQL Host"); m_dbS.setLocation(4, 128); m_gui.getContentPane().add(m_dbS); m_dbN = new JTextField(); m_dbN.setSize(128, 24); m_dbN.setText("MySQL Database Name"); m_dbN.setLocation(4, 160); m_gui.getContentPane().add(m_dbN); m_dbU = new JTextField(); m_dbU.setSize(128, 24); m_dbU.setText("MySQL Username"); m_dbU.setLocation(4, 192); m_gui.getContentPane().add(m_dbU); m_dbP = new JPasswordField(); m_dbP.setSize(128, 24); m_dbP.setText("Pass"); m_dbP.setLocation(4, 224); m_gui.getContentPane().add(m_dbP); m_name = new JTextField(); m_name.setSize(128, 24); m_name.setText("Your Server Name"); m_name.setLocation(4, 260); m_gui.getContentPane().add(m_name); /* * Load pre-existing settings if any */ File f = new File("res/settings.txt"); if(f.exists()) { try { Scanner s = new Scanner(f); m_dbS.setText(s.nextLine()); m_dbN.setText(s.nextLine()); m_dbU.setText(s.nextLine()); m_name.setText(s.nextLine()); s.close(); } catch (Exception e) { e.printStackTrace(); } } m_gui.setVisible(true); } /** * Starts the game server */ public void start() { /* * Store locally */ if(m_boolGui) { m_dbServer = m_dbS.getText(); m_dbName = m_dbN.getText(); m_dbUsername = m_dbU.getText(); m_dbPassword = new String(m_dbP.getPassword()); m_serverName = m_name.getText(); m_serviceManager = new ServiceManager(); m_serviceManager.start(); m_start.setEnabled(false); m_stop.setEnabled(true); } else { m_serviceManager = new ServiceManager(); m_serviceManager.start(); } } /** * Stops the game server */ public void stop() { m_serviceManager.stop(); if(m_boolGui){ m_start.setEnabled(true); m_stop.setEnabled(false); } else { try { /* Let threads finish up */ Thread.sleep(10000); /* Exit */ System.out.println("Exiting server..."); System.exit(0); } catch (Exception e) {} } } /** * Exits the game server application */ private void exit() { if(m_boolGui) if(m_stop.isEnabled()) { JOptionPane.showMessageDialog(null, "You must stop the server before exiting."); } else { System.exit(0); } else System.exit(0); } /** * Writes server settings to a file * NOTE: It never stores the database password */ private void saveSettings() { try { /* * Store globally */ if(m_boolGui){ m_dbServer = m_dbS.getText(); m_dbName = m_dbN.getText(); m_dbUsername = m_dbU.getText(); m_dbPassword = new String(m_dbP.getPassword()); m_serverName = m_name.getText(); } /* * Write to file */ File f = new File("res/settings.txt"); if(f.exists()) f.delete(); PrintWriter w = new PrintWriter(f); w.println(m_dbServer); w.println(m_dbName); w.println(m_dbUsername); w.println(m_serverName); w.println(" "); w.flush(); w.close(); } catch (Exception e) { e.printStackTrace(); } } /** * Updates the player count information * @param amount */ public void updatePlayerCount() { if(m_boolGui){ int amount = TcpProtocolHandler.getPlayerCount(); m_pAmount.setText(amount + " players online"); if(amount > m_highest) { m_highest = amount; m_pHighest.setText("Highest: " + amount); } } else { int amount = TcpProtocolHandler.getPlayerCount(); System.out.println(amount + " players online"); if(amount > m_highest) { m_highest = amount; System.out.println("Highest: " + amount); } } } /** * Returns the instance of game server * @return */ public static GameServer getInstance() { return m_instance; } /** * If you don't know what this method does, you clearly don't know enough Java to be working on this. * @param args */ public static void main(String [] args) { /* * Pipe errors to a file */ try { PrintStream p = new PrintStream(new File("./errors.txt")); System.setErr(p); } catch (Exception e) { e.printStackTrace(); } /* * Server settings */ Options options = new Options(); options.addOption("s","settings", true, "Can be low, medium, or high."); options.addOption("p","players", true, "Sets the max number of players."); options.addOption("ng", "nogui", false, "Starts server in headless mode."); options.addOption("ar", "autorun", false, "Runs without asking a single question."); options.addOption("h", "help", false, "Shows this menu."); if(args.length > 0) { CommandLineParser parser = new GnuParser(); try { // parse the command line arguments CommandLine line = parser.parse( options, args ); /* * The following sets the server's settings based on the * computing ability of the server specified by the server owner. */ if( line.hasOption( "settings" ) ) { String settings = line.getOptionValue( "settings" ); if(settings.equalsIgnoreCase("low")) { m_movementThreads = 4; } else if(settings.equalsIgnoreCase("medium")) { m_movementThreads = 8; } else if(settings.equalsIgnoreCase("high")) { m_movementThreads = 12; } else { System.err.println("Server requires a settings parameter"); HelpFormatter formatter = new HelpFormatter(); formatter.printHelp( "java GameServer [param] <args>", options ); System.exit(0); } }else{ System.err.println("Server requires a settings parameter"); HelpFormatter formatter = new HelpFormatter(); formatter.printHelp( "java GameServer [param] <args>", options ); System.exit(0); } if(line.hasOption("players")) { m_maxPlayers = Integer.parseInt(line.getOptionValue( "players" )); if(m_maxPlayers == 0 || m_maxPlayers == -1) m_maxPlayers = 99999; } else { System.err.println("WARNING: No maximum player count provided. Will default to 500 players."); m_maxPlayers = 500; } if(line.hasOption("help")){ HelpFormatter formatter = new HelpFormatter(); System.err.println("Server requires a settings parameter"); formatter.printHelp( "java GameServer [param] <args>", options ); } /* * Create the server gui */ @SuppressWarnings("unused") GameServer gs; if(line.hasOption("nogui")){ m_boolGui = false; if(line.hasOption("autorun")) gs = new GameServer(true); else gs = new GameServer(false); }else{ m_boolGui = true; if(line.hasOption("autorun")) System.out.println("autorun doesn't work with GUI"); gs = new GameServer(false); } } catch( ParseException exp ) { // oops, something went wrong System.err.println( "Parsing failed. Reason: " + exp.getMessage() ); // automatically generate the help statement HelpFormatter formatter = new HelpFormatter(); formatter.printHelp( "java GameServer [param] <args>", options ); } }else{ // automatically generate the help statement HelpFormatter formatter = new HelpFormatter(); System.err.println("Server requires a settings parameter"); formatter.printHelp( "java GameServer [param] <args>", options ); } } /** * Returns the service manager of the server * @return */ public static ServiceManager getServiceManager() { return m_serviceManager; } /** * Returns the amount of players this server will allow * @return */ public static int getMaxPlayers() { return m_maxPlayers; } /** * Returns the amount of movement threads running in this server * @return */ public static int getMovementThreadAmount() { return m_movementThreads; } /** * Returns the database host * @return */ public static String getDatabaseHost() { return m_dbServer; } /** * Returns the database username * @return */ public static String getDatabaseUsername() { return m_dbUsername; } /** * Returns the database password * @return */ public static String getDatabasePassword() { return m_dbPassword; } /** * Returns the name of this server * @return */ public static String getServerName() { return m_serverName; } /** * Returns the database selected * @return */ public static String getDatabaseName() { return m_dbName; } }