package client;
import common.*;
import common.messages.*;
import java.awt.event.*;
//import javax.swing.*;
import java.net.*;
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
//import java.nio.charset.Charset;
//import java.util.*;
/**
* Client connection to the server and other clients.
*/
public class ClientRawMulticastConnection implements ClientConnection, ActionListener, Constants, Runnable
{
private GameEngine engine;
private Thread thread = null;
// private boolean running;
private MulticastSocket mSocket;
private InetAddress myMCastGroup;
private int myMCastPort;
/**
* Creates a client connection to the server and other clients.
*
* @param engine
* @param serverName
* @param port
* @param userName
*/
public ClientRawMulticastConnection(GameEngine engine)
{
// running = false;
try
{
this.engine = engine;
} catch (Exception ex)
{
System.err.println("Could not connect to server!");
ex.printStackTrace();
}
}
public void setGameEngine(GameEngine engine)
{
this.engine = engine;
}
/**
* Logs into the specified server using the userName.
*/
public int loginToServer(String serverName, String userName) throws Exception
{
int playerId = -1;
// Create a ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(4096);
buffer.flip();
/*
* Avoid the server for now. Just connect to same Multicast Address
* // Connect to the specified server sockChannel.connect(new
* InetSocketAddress(serverName,DEFAULT_PORT)); // Create and send a
* login message byte[] loginMessage =
* LoginMessage.getLoginMessage(userName,"");
* System.out.println(LoginMessage.getMessageString(loginMessage));
* sockChannel.write(ByteBuffer.wrap(loginMessage)); // Receive a login
* success/failure sockChannel.read(buffer); byte[] loginSuccess =
* buffer.array();
* // Check if we successfully logged in
* if(LoginMessage.isLoginSuccessMessage(loginSuccess)) { int port =
* LoginMessage.getPort(loginSuccess); playerId =
* LoginMessage.getPlayerId(loginSuccess); System.out.printf("Port:
* %d\n", port);
* // create datagram channel & connect to rem port
* serverUDPChannel.configureBlocking(false);
* serverUDPChannel.connect(new InetSocketAddress(serverName,port));
* // get localport of datagram socket int localport =
* serverUDPChannel.socket().getLocalPort(); System.out.printf("UDP
* local port: %d\n", localport); // Register the UDP Channel with the
* selector
* serverUDPChannel.register(selector,serverUDPChannel.validOps());
* // send success message to send port number to server loginSuccess =
* LoginMessage.getLoginSuccessMessage((byte)playerId,MCAST_ADDRESS,localport);
* sockChannel.write(ByteBuffer.wrap(loginSuccess));
* // Get your multicast address and port myMCastGroup =
* InetAddress.getByName(MCAST_ADDRESS); myMCastPort = MCAST_PORT; //
* Set up the multicast parts of the application myMCastGroup =
* InetAddress.getByName(MCAST_ADDRESS); myMCastPort = MCAST_PORT;
* mSocket = new MulticastSocket(MCAST_PORT);
* mSocket.joinGroup(myMCastGroup);
* // Create a pipe to write back to the connection pipe = Pipe.open();
* source = pipe.source();
*
* source.configureBlocking(false);
* source.register(selector,SelectionKey.OP_READ);
* // Notify everyone that we have joined PlayerJoinMessage message =
* new PlayerJoinMessage((byte)engine.localPlayer.getPlayerId(),
* myMCastGroup, engine.localPlayer.getPlayerName());
* sendMessage(message);
*
* reader = new MulticastReader(mSocket,pipe.sink()); reader.start(); }
* else { System.err.println("Unable to log in!"); }
*/
// Get your multicast address and port
myMCastGroup = InetAddress.getByName(MCAST_ADDRESS);
myMCastPort = MCAST_PORT;
// Set up the multicast parts of the application
mSocket = new MulticastSocket(MCAST_PORT);
mSocket.joinGroup(myMCastGroup);
if (mSocket.getReceiveBufferSize() < 1024 * 128)
mSocket.setReceiveBufferSize(1024 * 128);
System.out.printf("Multicast port number: %d\n", mSocket.getLocalPort());
System.out.printf("Packets have a timeToLive of %d\n", mSocket.getTimeToLive());
// Create a pipe to write back to the connection
//pipe = Pipe.open();
//source = pipe.source();
//source.configureBlocking(false);
// source.register(selector,SelectionKey.OP_READ);
// Notify everyone that we have joined
// PlayerJoinMessage message = new
// PlayerJoinMessage((byte)engine.localPlayer.getPlayerID(),
// new InetSocketAddress(myMCastGroup,myMCastPort),
// engine.localPlayer.getPlayerName());
// sendMessage(message);
//reader = new MulticastReader(mSocket, pipe.sink());
//reader.start();
return playerId;
}
/**
* Checks if messages have been sent to the client.
*/
public void checkMessages()
{
if (mSocket == null)
return;
DatagramPacket packet = new DatagramPacket(new byte[4096], 4096);
try
{
mSocket.receive(packet);
// System.out.printf("Got a packet of length %d.\n",
// packet.getLength());
processMessage(packet.getData());
} catch (IOException er)
{
er.printStackTrace();
}
} // end checkMessages()
/**
* Processes a SelectorKey (Message) that has come in.
*
* @param selKey
* Key that is associated with a message.
* @param buffer
* The buffer to use to store the messages.
*/
protected void processMessage(SelectionKey selKey, ByteBuffer buffer) throws Exception
{
// Since the ready operations are cumulative,
// need to check readiness for each operation
if (selKey.isValid() && selKey.isReadable())
{
// Get channel with connection request
//source.read(buffer);
//buffer.rewind();
// Get the message from the buffer
Message message = MessageAnalyzer.getMessage(buffer);
if (message == null)
return;
if (message.getPlayerId() == engine.localPlayer.getPlayerID())
return;
switch (message.getMessageType())
{
case PlayerMotion:
engine.processPlayerMotion((PlayerMotionMessage) message);
System.out.printf("PlayerMotion: %d moved to\t(%.2f,%.2f)\n", message.getPlayerId(), ((PlayerMotionMessage) message).getPosition().getX(), ((PlayerMotionMessage) message).getPosition().getY());
break;
case PlayerJoin:
PlayerJoinMessage msg = (PlayerJoinMessage) message;
System.out.println("PlayerJoin: " + msg.getName() + " wants to join");
engine.processPlayerJoin(msg);
registerPlayer(msg.getPlayerId(), msg.getAddress());
break;
default:
System.out.println("Got Undefined Message");
break;
}
}
}
protected void processMessage(byte[] data)
{
try
{
Message message = MessageAnalyzer.getMessage(data);
if (message.getPlayerId() == engine.localPlayer.getPlayerID())
return;
switch (message.getMessageType())
{
case PlayerMotion:
engine.processPlayerMotion((PlayerMotionMessage) message);
System.out.printf("PlayerMotion: %d moved to\t(%.2f,%.2f)\n", message.getPlayerId(), ((PlayerMotionMessage) message).getPosition().getX(), ((PlayerMotionMessage) message).getPosition().getY());
break;
case PlayerJoin:
PlayerJoinMessage msg = (PlayerJoinMessage) message;
System.out.println("PlayerJoin: " + msg.getName() + " wants to join");
engine.processPlayerJoin(msg);
registerPlayer(msg.getPlayerId(), msg.getAddress());
break;
default:
System.out.println("Got Undefined Message");
break;
}
} catch (Exception er)
{
er.printStackTrace();
}
}
/**
* Sends a message through the multicast socket. Client does not subscribe
* to their own multicast group.
*
* @param The
* message to be sent.
*/
public void sendMessage(Message message) throws Exception
{
byte[] byteMessage = message.getByteMessage();
DatagramPacket packet = new DatagramPacket(byteMessage, byteMessage.length, myMCastGroup, myMCastPort);
mSocket.send(packet);
}
/**
*
*/
protected void registerPlayer(int playerId, InetSocketAddress mcastAddress)
{
}
/**
*
*/
public void actionPerformed(ActionEvent e)
{
try
{
checkMessages();
// Send motion message for this player
// sendMessage(new
// PlayerMotionMessage((byte)engine.localPlayer.getPlayerID(),
// engine.localPlayer.getPosition(),
// engine.localPlayer.getVelocity(),
// (float)System.currentTimeMillis()));
PlayerMotionMessage pmm = engine.localPlayer.getMotionPacket(engine.currentTime);
// System.out.printf("Sending PlayerMotionMessage\n");
sendMessage(pmm);
} catch (Exception ex)
{
ex.printStackTrace();
}
}
public void run()
{
while (true)
{
checkMessages();
try
{
Thread.sleep(10);
} catch (InterruptedException er)
{
}
// Thread.yield();
}
}
public void stopSendingMessages()
{
}
public void start()
{
if (thread == null)
thread = new Thread(this);
thread.start();
}
public void stop()
{
// TODO Auto-generated method stub
}
/**
*
*/
// public void start() {
// timer = new javax.swing.Timer(TIMER_TICK, this);
// timer.start();
// timer.setCoalesce(true);
// }
}