/*******************************************************************************
* Copyright (c) 2015
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*******************************************************************************/
package jsettlers.network.server;
import java.util.Timer;
import jsettlers.network.NetworkConstants;
import jsettlers.network.common.packets.ChatMessagePacket;
import jsettlers.network.common.packets.OpenNewMatchPacket;
import jsettlers.network.common.packets.TimeSyncPacket;
import jsettlers.network.infrastructure.channel.Channel;
import jsettlers.network.infrastructure.channel.reject.RejectPacket;
import jsettlers.network.server.db.IDBFacade;
import jsettlers.network.server.exceptions.NotAllPlayersReadyException;
import jsettlers.network.server.listeners.ChatMessageForwardingListener;
import jsettlers.network.server.listeners.IdentifyUserListener;
import jsettlers.network.server.listeners.ReadyStatePacketListener;
import jsettlers.network.server.listeners.ServerChannelClosedListener;
import jsettlers.network.server.listeners.StartFinishedSignalListener;
import jsettlers.network.server.listeners.TimeSyncForwardingListener;
import jsettlers.network.server.listeners.matches.JoinMatchListener;
import jsettlers.network.server.listeners.matches.LeaveMatchListener;
import jsettlers.network.server.listeners.matches.OpenNewMatchListener;
import jsettlers.network.server.listeners.matches.StartMatchListener;
import jsettlers.network.server.match.Match;
import jsettlers.network.server.match.MatchesListSendingTimerTask;
import jsettlers.network.server.match.Player;
/**
* This class is the central access point to the servers externally reachable functions.
*
* @author Andreas Eberle
*
*/
public class ServerManager implements IServerManager {
private final IDBFacade database;
private final Timer sendMatchesListTimer = new Timer("SendMatchesListTimer", true);
private final Timer matchesTaskDistributionTimer = new Timer("MatchesTaskDistributionTimer", true);
private final MatchesListSendingTimerTask matchSendingTask;
public ServerManager(IDBFacade db) {
this.database = db;
matchSendingTask = new MatchesListSendingTimerTask(db);
}
public synchronized void start() {
sendMatchesListTimer.schedule(matchSendingTask, 0, NetworkConstants.Server.OPEN_MATCHES_SEND_INTERVAL_MS);
}
public synchronized void shutdown() {
sendMatchesListTimer.cancel();
matchesTaskDistributionTimer.cancel();
}
public void identifyNewChannel(Channel channel) {
channel.registerListener(new IdentifyUserListener(channel, this));
}
@Override
public boolean acceptNewPlayer(Player player) {
if (database.isAcceptedPlayer(player.getId())) {
database.storePlayer(player);
Channel channel = player.getChannel();
channel.removeListener(NetworkConstants.ENetworkKey.IDENTIFY_USER);
channel.setChannelClosedListener(new ServerChannelClosedListener(this, player));
channel.registerListener(new OpenNewMatchListener(this, player));
channel.registerListener(new LeaveMatchListener(this, player));
channel.registerListener(new StartMatchListener(this, player));
channel.registerListener(new JoinMatchListener(this, player));
channel.registerListener(new ChatMessageForwardingListener(this, player));
channel.registerListener(new TimeSyncForwardingListener(this, player));
channel.registerListener(new ReadyStatePacketListener(this, player));
channel.registerListener(new StartFinishedSignalListener(this, player));
return true;
} else {
return false;
}
}
@Override
public void channelClosed(Player player) {
if (player.isInMatch()) {
try {
player.leaveMatch();
} catch (IllegalStateException e) {
assert false : "This may never happen here!";
}
}
database.removePlayer(player);
}
@Override
public void createNewMatch(OpenNewMatchPacket matchInfo, Player player) {
Match match = new Match(matchInfo.getMatchName(), matchInfo.getMaxPlayers(), matchInfo.getMapInfo(), matchInfo.getRandomSeed());
database.storeMatch(match);
joinMatch(match, player);
}
private void joinMatch(Match match, Player player) {
try {
player.joinMatch(match);
} catch (IllegalStateException e) {
e.printStackTrace();
player.sendPacket(NetworkConstants.ENetworkKey.REJECT_PACKET,
new RejectPacket(NetworkConstants.ENetworkMessage.INVALID_STATE_ERROR, NetworkConstants.ENetworkKey.REQUEST_OPEN_NEW_MATCH));
}
}
@Override
public void leaveMatch(Player player) {
player.leaveMatch();
}
@Override
public void startMatch(Player player) {
try {
player.startMatch(matchesTaskDistributionTimer);
} catch (IllegalStateException e) {
e.printStackTrace();
player.sendPacket(NetworkConstants.ENetworkKey.REJECT_PACKET,
new RejectPacket(NetworkConstants.ENetworkMessage.INVALID_STATE_ERROR, NetworkConstants.ENetworkKey.REQUEST_START_MATCH));
} catch (NotAllPlayersReadyException e) {
player.sendPacket(NetworkConstants.ENetworkKey.REJECT_PACKET,
new RejectPacket(NetworkConstants.ENetworkMessage.NOT_ALL_PLAYERS_READY, NetworkConstants.ENetworkKey.REQUEST_START_MATCH));
}
}
@Override
public void forwardChatMessage(Player player, ChatMessagePacket packet) {
try {
player.forwardChatMessage(packet);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
public void distributeTimeSync(Player player, TimeSyncPacket packet) {
try {
player.distributeTimeSync(packet);
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
public void joinMatch(String matchId, Player player) {
Match match = database.getMatchById(matchId);
try {
player.joinMatch(match);
} catch (IllegalStateException e) {
player.sendPacket(NetworkConstants.ENetworkKey.REJECT_PACKET,
new RejectPacket(NetworkConstants.ENetworkMessage.INVALID_STATE_ERROR, NetworkConstants.ENetworkKey.REQUEST_JOIN_MATCH));
}
}
@Override
public void setReadyStateForPlayer(Player player, boolean ready) {
try {
player.setReady(ready);
} catch (IllegalStateException e) {
player.sendPacket(NetworkConstants.ENetworkKey.REJECT_PACKET,
new RejectPacket(NetworkConstants.ENetworkMessage.INVALID_STATE_ERROR, NetworkConstants.ENetworkKey.CHANGE_READY_STATE));
}
}
@Override
public void sendMatchesToPlayer(Player player) {
matchSendingTask.sendMatchesTo(player);
}
@Override
public void setStartFinished(Player player, boolean startFinished) {
player.setStartFinished(startFinished);
}
public IDBFacade getDatabase() {
return database;
}
}