|
|
|
|
@@ -0,0 +1,235 @@
|
|
|
|
|
package pp.mdga.client.server;
|
|
|
|
|
|
|
|
|
|
import com.jme3.network.*;
|
|
|
|
|
import com.jme3.network.serializing.Serializer;
|
|
|
|
|
import pp.mdga.game.Game;
|
|
|
|
|
import pp.mdga.game.Player;
|
|
|
|
|
import pp.mdga.message.client.*;
|
|
|
|
|
import pp.mdga.message.server.*;
|
|
|
|
|
import pp.mdga.server.ServerGameLogic;
|
|
|
|
|
import pp.mdga.server.ServerSender;
|
|
|
|
|
|
|
|
|
|
import java.io.FileInputStream;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.lang.System.Logger;
|
|
|
|
|
import java.lang.System.Logger.Level;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.concurrent.BlockingQueue;
|
|
|
|
|
import java.util.concurrent.LinkedBlockingQueue;
|
|
|
|
|
import java.util.logging.LogManager;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Server implementing the visitor pattern as MessageReceiver for ClientMessages
|
|
|
|
|
*/
|
|
|
|
|
public class MdgaServer implements MessageListener<HostedConnection>, ConnectionListener, ServerSender {
|
|
|
|
|
private static final Logger LOGGER = System.getLogger(MdgaServer.class.getName());
|
|
|
|
|
|
|
|
|
|
private Server myServer;
|
|
|
|
|
private final ServerGameLogic logic;
|
|
|
|
|
private final BlockingQueue<ReceivedMessage> pendingMessages = new LinkedBlockingQueue<>();
|
|
|
|
|
|
|
|
|
|
static {
|
|
|
|
|
// Configure logging
|
|
|
|
|
LogManager manager = LogManager.getLogManager();
|
|
|
|
|
try {
|
|
|
|
|
manager.readConfiguration(new FileInputStream("logging.properties"));
|
|
|
|
|
LOGGER.log(Level.INFO, "Successfully read logging properties"); //NON-NLS
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
LOGGER.log(Level.INFO, e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Starts the Battleships server.
|
|
|
|
|
*/
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
new MdgaServer().run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new MdgaServer.
|
|
|
|
|
*/
|
|
|
|
|
public MdgaServer() {
|
|
|
|
|
LOGGER.log(Level.INFO, "Creating MdgaServer"); //NON-NLS
|
|
|
|
|
logic = new ServerGameLogic(this, new Game());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void run() {
|
|
|
|
|
startServer();
|
|
|
|
|
this.connectionAdded(myServer, myServer.getConnection(0));
|
|
|
|
|
while (true)
|
|
|
|
|
processNextMessage();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void startServer() {
|
|
|
|
|
try {
|
|
|
|
|
LOGGER.log(Level.INFO, "Starting server..."); //NON-NLS
|
|
|
|
|
myServer = Network.createServer(1234);
|
|
|
|
|
|
|
|
|
|
initializeSerializables();
|
|
|
|
|
myServer.start();
|
|
|
|
|
registerListeners();
|
|
|
|
|
LOGGER.log(Level.INFO, "Server started: {0}", myServer.isRunning()); //NON-NLS
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
LOGGER.log(Level.ERROR, "Couldn't start server: {0}", e.getMessage()); //NON-NLS
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void processNextMessage() {
|
|
|
|
|
try {
|
|
|
|
|
pendingMessages.take().process(logic);
|
|
|
|
|
} catch (InterruptedException ex) {
|
|
|
|
|
LOGGER.log(Level.INFO, "Interrupted while waiting for messages"); //NON-NLS
|
|
|
|
|
Thread.currentThread().interrupt();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initializeSerializables() {
|
|
|
|
|
Serializer.registerClass(AnimationEnd.class);
|
|
|
|
|
Serializer.registerClass(ClientStartGame.class);
|
|
|
|
|
Serializer.registerClass(DeselectTSK.class);
|
|
|
|
|
Serializer.registerClass(ForceContinueGame.class);
|
|
|
|
|
Serializer.registerClass(StartGame.class);
|
|
|
|
|
Serializer.registerClass(JoinServer.class);
|
|
|
|
|
Serializer.registerClass(LeaveGame.class);
|
|
|
|
|
Serializer.registerClass(LobbyNotReady.class);
|
|
|
|
|
Serializer.registerClass(LobbyReady.class);
|
|
|
|
|
Serializer.registerClass(NoPowerCard.class);
|
|
|
|
|
Serializer.registerClass(RequestBriefing.class);
|
|
|
|
|
Serializer.registerClass(RequestDie.class);
|
|
|
|
|
Serializer.registerClass(RequestMove.class);
|
|
|
|
|
Serializer.registerClass(RequestPlayCard.class);
|
|
|
|
|
Serializer.registerClass(SelectCard.class);
|
|
|
|
|
Serializer.registerClass(SelectedPieces.class);
|
|
|
|
|
Serializer.registerClass(SelectTSK.class);
|
|
|
|
|
|
|
|
|
|
Serializer.registerClass(ActivePlayer.class);
|
|
|
|
|
Serializer.registerClass(AnyPiece.class);
|
|
|
|
|
Serializer.registerClass(Briefing.class);
|
|
|
|
|
Serializer.registerClass(CeremonyMessage.class);
|
|
|
|
|
Serializer.registerClass(Die.class);
|
|
|
|
|
Serializer.registerClass(DiceAgain.class);
|
|
|
|
|
Serializer.registerClass(DiceNow.class);
|
|
|
|
|
Serializer.registerClass(EndOfTurn.class);
|
|
|
|
|
Serializer.registerClass(LobbyAccept.class);
|
|
|
|
|
Serializer.registerClass(LobbyDeny.class);
|
|
|
|
|
Serializer.registerClass(LobbyPlayerJoin.class);
|
|
|
|
|
Serializer.registerClass(LobbyPlayerLeave.class);
|
|
|
|
|
Serializer.registerClass(MoveMessage.class);
|
|
|
|
|
Serializer.registerClass(NoTurn.class);
|
|
|
|
|
Serializer.registerClass(PauseGame.class);
|
|
|
|
|
Serializer.registerClass(PlayCard.class);
|
|
|
|
|
Serializer.registerClass(PossibleCard.class);
|
|
|
|
|
Serializer.registerClass(PossiblePiece.class);
|
|
|
|
|
Serializer.registerClass(RankingResponse.class);
|
|
|
|
|
Serializer.registerClass(RankingRollAgain.class);
|
|
|
|
|
Serializer.registerClass(ReconnectBriefing.class);
|
|
|
|
|
Serializer.registerClass(ResumeGame.class);
|
|
|
|
|
Serializer.registerClass(ServerStartGame.class);
|
|
|
|
|
Serializer.registerClass(StartPiece.class);
|
|
|
|
|
Serializer.registerClass(UpdateReady.class);
|
|
|
|
|
Serializer.registerClass(UpdateTSK.class);
|
|
|
|
|
Serializer.registerClass(WaitPiece.class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void registerListeners() {
|
|
|
|
|
myServer.addMessageListener(this, AnimationEnd.class);
|
|
|
|
|
myServer.addMessageListener(this, ClientStartGame.class);
|
|
|
|
|
myServer.addMessageListener(this, DeselectTSK.class);
|
|
|
|
|
myServer.addMessageListener(this, ForceContinueGame.class);
|
|
|
|
|
myServer.addMessageListener(this, StartGame.class);
|
|
|
|
|
myServer.addMessageListener(this, JoinServer.class);
|
|
|
|
|
myServer.addMessageListener(this, LeaveGame.class);
|
|
|
|
|
myServer.addMessageListener(this, LobbyNotReady.class);
|
|
|
|
|
myServer.addMessageListener(this, LobbyReady.class);
|
|
|
|
|
myServer.addMessageListener(this, NoPowerCard.class);
|
|
|
|
|
myServer.addMessageListener(this, RequestBriefing.class);
|
|
|
|
|
myServer.addMessageListener(this, RequestDie.class);
|
|
|
|
|
myServer.addMessageListener(this, RequestMove.class);
|
|
|
|
|
myServer.addMessageListener(this, RequestPlayCard.class);
|
|
|
|
|
myServer.addMessageListener(this, SelectCard.class);
|
|
|
|
|
myServer.addMessageListener(this, SelectedPieces.class);
|
|
|
|
|
myServer.addMessageListener(this, SelectTSK.class);
|
|
|
|
|
myServer.addConnectionListener(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void messageReceived(HostedConnection source, ClientMessage message) {
|
|
|
|
|
LOGGER.log(Level.INFO, "message received from {0}: {1}", source.getId(), message); //NON-NLS
|
|
|
|
|
pendingMessages.add(new ReceivedMessage(message, source.getId()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void connectionAdded(Server server, HostedConnection hostedConnection) {
|
|
|
|
|
LOGGER.log(Level.INFO, "new connection {0}", hostedConnection); //NON-NLS
|
|
|
|
|
// ToDo: Synchronize data between server and client.
|
|
|
|
|
logic.getGame().addPlayer(hostedConnection.getId(), new Player());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void connectionRemoved(Server server, HostedConnection hostedConnection) {
|
|
|
|
|
LOGGER.log(Level.INFO, "connection closed: {0}", hostedConnection); //NON-NLS
|
|
|
|
|
final Player player = logic.getGame().getPlayerById(hostedConnection.getId());
|
|
|
|
|
if (player == null)
|
|
|
|
|
LOGGER.log(Level.INFO, "closed connection does not belong to an active player"); //NON-NLS
|
|
|
|
|
else { //NON-NLS
|
|
|
|
|
LOGGER.log(Level.INFO, "closed connection belongs to {0}", player); //NON-NLS
|
|
|
|
|
// exit(0);
|
|
|
|
|
this.handleDisconnect(hostedConnection.getId());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This method will be used to handle unintentional disconnections from players.
|
|
|
|
|
*
|
|
|
|
|
* @param id as the id of the disconnected player.
|
|
|
|
|
*/
|
|
|
|
|
public void handleDisconnect(int id) {
|
|
|
|
|
this.logic.received(new Disconnected(), id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void exit(int exitValue) { //NON-NLS
|
|
|
|
|
LOGGER.log(Level.INFO, "close request"); //NON-NLS
|
|
|
|
|
if (myServer != null)
|
|
|
|
|
for (HostedConnection client : myServer.getConnections()) //NON-NLS
|
|
|
|
|
if (client != null) client.close("Game over"); //NON-NLS
|
|
|
|
|
System.exit(exitValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Send the specified message to the specified connection.
|
|
|
|
|
*
|
|
|
|
|
* @param id the connection id
|
|
|
|
|
* @param message the message
|
|
|
|
|
*/
|
|
|
|
|
public void send(int id, ServerMessage message) {
|
|
|
|
|
if (myServer == null || !myServer.isRunning()) {
|
|
|
|
|
LOGGER.log(Level.ERROR, "no server running when trying to send {0}", message); //NON-NLS
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
final HostedConnection connection = myServer.getConnection(id);
|
|
|
|
|
if (connection != null)
|
|
|
|
|
connection.send(message);
|
|
|
|
|
else
|
|
|
|
|
LOGGER.log(Level.ERROR, "there is no connection with id={0}", id); //NON-NLS
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This method will be used to send the given message parameter to all connected players which are saved inside the
|
|
|
|
|
* players attribute of Game class.
|
|
|
|
|
*
|
|
|
|
|
* @param message as the message which will be sent to all players as a ServerMessage.
|
|
|
|
|
*/
|
|
|
|
|
public void broadcast(ServerMessage message) {
|
|
|
|
|
for (Map.Entry<Integer, Player> entry: this.logic.getGame().getPlayers().entrySet()) {
|
|
|
|
|
this.send(entry.getKey(), message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TODO:
|
|
|
|
|
@Override
|
|
|
|
|
public void messageReceived(HostedConnection source, Message m) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|