package com.esotericsoftware.kryonet.examples.chatrmi; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import java.util.ArrayList; import javax.swing.JFrame; import javax.swing.JLabel; import com.esotericsoftware.kryonet.Connection; import com.esotericsoftware.kryonet.Listener; import com.esotericsoftware.kryonet.Server; import com.esotericsoftware.kryonet.rmi.ObjectSpace; import com.esotericsoftware.minlog.Log; // This class is the server for a simple chat client/server example that uses RMI. // It is recommended to review the non-RMI chat example first. // While this example uses only RMI, RMI can be mixed with non-RMI KryoNet usage. // RMI has more overhead (usually 4 bytes) then just sending an object. public class ChatRmiServer { Server server; ArrayList<Player> players = new ArrayList(); public ChatRmiServer () throws IOException { server = new Server() { protected Connection newConnection () { // Each connection represents a player and has fields // to store state and methods to perform actions. Player player = new Player(); players.add(player); return player; } }; // Register the classes that will be sent over the network. Network.register(server); server.addListener(new Listener() { public void disconnected (Connection connection) { Player player = (Player)connection; players.remove(player); if (player.name != null) { // Announce to everyone that someone (with a registered name) has left. String message = player.name + " disconnected."; for (Player p : players) p.frame.addMessage(message); updateNames(); } } }); server.bind(Network.port); server.start(); // Open a window to provide an easy way to stop the server. JFrame frame = new JFrame("Chat RMI Server"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { public void windowClosed (WindowEvent evt) { server.stop(); } }); frame.getContentPane().add(new JLabel("Close to stop the chat server.")); frame.setSize(320, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); } void updateNames () { // Collect the names of each player. ArrayList namesList = new ArrayList(players.size()); for (Player player : players) if (player.name != null) namesList.add(player.name); // Set the names on everyone's chat frame. String[] names = (String[])namesList.toArray(new String[namesList.size()]); for (Player player : players) player.frame.setNames(names); } class Player extends Connection implements IPlayer { IChatFrame frame; String name; public Player () { // Each connection has an ObjectSpace containing the Player. // This allows the other end of the connection to call methods on the Player. new ObjectSpace(this).register(Network.PLAYER, this); // Get the ChatFrame on the other end of the connection. // This allows the server to call methods on the client. frame = ObjectSpace.getRemoteObject(this, Network.CHAT_FRAME, IChatFrame.class); } public void registerName (String name) { // Do nothing if the player already registered a name. if (this.name != null) return; // Do nothing if the name is invalid. if (name == null) return; name = name.trim(); if (name.length() == 0) return; // Store the player's name. this.name = name; // Add a "connected" message to everyone's chat frame, except the new player. String message = name + " connected."; for (Player player : players) if (player != this) player.frame.addMessage(message); // Set the names on everyone's chat frame. updateNames(); } public void sendMessage (String message) { // Do nothing if a player tries to chat before registering a name. if (this.name == null) return; // Do nothing if the chat message is invalid. if (message == null) return; message = message.trim(); if (message.length() == 0) return; // Prepend the player's name and add to everyone's chat frame. message = this.name + ": " + message; for (Player player : players) player.frame.addMessage(message); } } public static void main (String[] args) throws IOException { Log.set(Log.LEVEL_DEBUG); new ChatRmiServer(); } }