/** Starts the server, and waits for clients. */ public Server() { instance = this; System.out.println( "== SERVER v" + Constants.NETCODE_VERSION + " == started at IP address: " + getLocalIP()); clients = new LinkedList<ClientMachine>(); try { beginListening(Constants.DEFAULT_PORT); } catch (BindException e) { Main.fatalError( "Couldn't bind to port " + Constants.DEFAULT_PORT + ". Perhaps a server is already running?\n\n" + e.getLocalizedMessage()); } catch (SocketException ex) { ex.printStackTrace(); } }
/** * Called when we receive a packet from a client. Deciphers what the client is telling us, and * responds. */ @Override void parseReceived(DatagramPacket p) { try { // Ensure this client is on our register. ClientMachine client = registerClient(new Machine(p.getAddress(), p.getPort())); ByteInputStream in = new ByteInputStream(p.getData()); // Determine the type of message. int command = in.readInt(); if ((command >= 0) && (command < Client.Message.values().length)) { switch (Client.Message.values()[command]) { // Client wants to join the game. case CONNECT: ByteOutputStream out = new ByteOutputStream(); // If he's using an older netcode version, slam the door in his face. int version = in.readInt(); if (version < Constants.NETCODE_VERSION) { out.writeInt(ServerCommands.Message.CONNECT_ERROR_OLDNETCODE.ordinal()); out.writeInt(Constants.NETCODE_VERSION); sendPacket(client, out); Main.log( "Connection from " + client.toString() + " refused, using old version: " + version + ".", 800); return; } Main.log("Connection from " + client.toString() + " accepted."); // Spawn him in (so he'll be included in the update). long id = Game.getInstance().addPlayer(in.readUTF(), new Color(in.readInt())); // Send him a full update. out.writeInt(ServerCommands.Message.FULL_UPDATE.ordinal()); Game.getInstance().flatten(out); out.writeLong(id); // Associate this client with the ship. client.inGamePlayer = (Ship) Game.getInstance().getObjectManager().getObject(id); // Waddle this fat packet out the door! sendPacket(client, out); // Tell everyone else about the player joining. out = new ByteOutputStream(); out.writeInt(ServerCommands.Message.PLAYER_JOINED.ordinal()); client.inGamePlayer.flatten(out); sendPacketToAllButOnePlayer(out, client); break; // Client is sending us a keystroke. case KEYSTROKE: if (!client.isInGame()) break; int keyCode = in.readInt(); Game.getInstance() .getActionManager() .add(new Action(client.inGamePlayer, keyCode, Game.getInstance().timeStep + 2)); break; // Client is telling us he's still here. case PONG: client.see(); break; // Client wishes to resume life. case QUITTING: if (!client.isInGame()) break; Game.getInstance().removePlayer(client.inGamePlayer); // Tell everyone else. out = new ByteOutputStream(); out.writeInt(ServerCommands.Message.PLAYER_QUIT.ordinal()); out.writeBoolean(false); // Not a timeout. out.writeLong(client.inGamePlayer.getId()); sendPacketToAllButOnePlayer(out, client); } } } catch (IOException ex) { Main.fatalError("Server parsing exception.", ex); } }