package complexion.server;
import java.io.IOException;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import complexion.network.message.InputData;
import complexion.network.message.LoginAccepted;
import complexion.network.message.LoginRequest;
import complexion.network.message.RegisterClasses;
/**
* This class is responsible for managing network connections.
* It will mostly be responsible for accepting and creating new
* connections.
*/
public class ServerListener extends Listener
{
/**
* Create a new ServerListener, which will automatically
* bind a TCP socket to localhost
* @param port The port to host the server on.
* @throws IOException
*/
public ServerListener(Server server, int port) throws IOException
{
// Remember the server we were created from
this.server = server;
// Create the server(huge name needed due to naming conflict)
server_socket =
new com.esotericsoftware.kryonet.Server(16384 ,3072);
// Setup message classes for transfer.
RegisterClasses.registerClasses(server_socket.getKryo());
// Register our custom listener
server_socket.addListener(this);
server_socket.bind(port);
server_socket.start();
}
/**
* Handle the incoming message.
*
* Note that this will be running in a separate thread. Thus, all operations
* performed from this function(and its descendends) must either operate on local
* values, or operate on threadsafe calls.
*
* Anything interacting with game-world data must be done by writing
* requests into a thread-safe structure, and having the master controller
* poll this structure.
*/
@Override
public void received(Connection connection, Object object)
{
// Check if this is the first message from that connection.
if(!server.clientsByIP.containsKey(connection))
{
// New connection, add it to the client list, and do it concurrently
Client new_client = new Client();
Client previous_value =
server.clientsByIP.putIfAbsent(connection, new_client);
// Now make sure we didn't have another thread trying to register itself
// at the same time.
if(previous_value != null)
{
Thread.dumpStack();
System.out.println("Unhandled concurrency violation.");
System.exit(1);
}
// Try to handle a login message
boolean login_success = false;
// Okay, looks like we're the only one. Try to register the client.
if(object instanceof LoginRequest)
{
LoginRequest request = (LoginRequest) object;
if(server.handleLoginRequest(request.account_name, request.password))
{
login_success = true; // We're good, bro
// Notify the client that the login was successful
LoginAccepted data = new LoginAccepted();
data.tick = server.getTick();
connection.sendTCP(data);
// Finish initializing the client.
new_client.account_name = request.account_name;
new_client.connection = new ClientConnection(new_client, connection);
new_client.initialize();
}
}
if(!login_success)
{
// Login seems to have failed, kill the connection
connection.close();
}
}
}
/// The game server instance this listener was crated from.
private Server server;
private com.esotericsoftware.kryonet.Server server_socket;
}