Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import com.mycompany.tictactoeserver.domain.entity.PlayerEntity;
import com.mycompany.tictactoeserver.domain.entity.PlayerStatus;
import com.mycompany.tictactoeserver.domain.services.communication.*;
import com.mycompany.tictactoeserver.domain.services.communication.MessageRouter;
import com.mycompany.tictactoeserver.domain.services.game.GameManager;
import com.mycompany.tictactoeserver.domain.services.statistics.StatisticsService;
import com.mycompany.tictactoeserver.domain.utils.callbacks.PlayerHandlerCallback;
import com.mycompany.tictactoeserver.domain.utils.exception.ExceptionHandlerMiddleware;
import com.mycompany.tictactoeserver.domain.utils.exception.PlayerSendMessageException;
Expand All @@ -13,8 +16,8 @@
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.List;
import java.util.Vector;

public class GameServerManager {

private final Vector<PlayerConnectionHandler> players = new Vector<>();
Expand Down Expand Up @@ -67,10 +70,39 @@ public Vector<Player> getAvailablePlayerData() {
return available;
}

public Message getAvailablePlayersMessage(PlayerConnectionHandler requester) {
Vector<PlayerEntity> online = new Vector<>();
Vector<PlayerEntity> inGame = new Vector<>();
Vector<PlayerEntity> pending = new Vector<>();
public Message getLeaderboardMessage() {
StatisticsService statsService = new StatisticsService();

List<PlayerEntity> topPlayersList = statsService.getLeaderboard();

Vector<PlayerEntity> leaderboardVector = new Vector<>(topPlayersList);

AvailablePlayersInfo info = new AvailablePlayersInfo(leaderboardVector, null, null);

return Message.createMessage(MessageType.RESPONSE, Action.GET_LEADERBOARD, info);
}

public void broadcastLeaderboard() {
Message msg = getLeaderboardMessage();
String jsonMsg = gson.toJson(msg);

synchronized (lock) {
for (PlayerConnectionHandler player : players) {
try {
if (player.getPlayer() != null) {
player.sendMessageToPlayer(jsonMsg);
}
} catch (Exception e) {
System.out.println("Error broadcasting leaderboard: " + e.getMessage());
}
}
}
}

public Message getAvailablePlayersMessage(PlayerConnectionHandler requester) {
Vector<PlayerEntity> online = new Vector<>();
Vector<PlayerEntity> inGame = new Vector<>();
Vector<PlayerEntity> pending = new Vector<>();

synchronized (lock) {
for (PlayerConnectionHandler handler : players) {
Expand All @@ -97,15 +129,15 @@ public Message getAvailablePlayersMessage(PlayerConnectionHandler requester) {

AvailablePlayersInfo info = new AvailablePlayersInfo(online, inGame, pending);
return Message.createMessage(MessageType.RESPONSE, Action.GET_AVAILABLE_PLAYERS, info);
}

}

public void start() {
synchronized (lock) {
System.out.println("Starting GameServerManager");
runnable.toggleRunning();
}
}

public void stop() {
System.out.println("Stopping GameServerManager");
runnable.toggleRunning();
Expand Down Expand Up @@ -168,6 +200,7 @@ public void addPlayer(PlayerConnectionHandler player) {
}

public void removePlayer(PlayerConnectionHandler player) {
GameManager.getInstance().handlePlayerDisconnect(player);
synchronized (lock) {
players.remove(player);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public Message register(AuthRequestEntity credential) {
playerDao.insert(newPlayer);

AuthResponseEntity responseEntity = new AuthResponseEntity(newPlayer);
response = Message.createMessage(MessageType.RESPONSE, Action.REGISTERATION_SUCCESS, responseEntity);
response = Message.createMessage(MessageType.RESPONSE, Action.REGISTERATION_SUCCESS, responseEntity);

} catch (HashingException ex) {
ServerInterruptException customException = new ServerInterruptException(ex.getStackTrace());
Expand All @@ -74,6 +74,7 @@ public Message register(AuthRequestEntity credential) {
response = Message.createMessage(MessageType.ERROR, Action.INTERNAL_SERVER_ERROR, credential);
return response;
}

return response;
}

Expand All @@ -92,6 +93,7 @@ public Message login(AuthRequestEntity credential, PlayerConnectionHandler clien
return response;
}


GameServerManager.getInstance().broadcastPlayerList();
String hashedPassword = ServerSecurityManager.hashText(credential.getPassword());
if (!hashedPassword.equals(player.getPassword())) {
Expand All @@ -108,9 +110,13 @@ public Message login(AuthRequestEntity credential, PlayerConnectionHandler clien
AuthResponseEntity responseEntity = new AuthResponseEntity(player);
response = Message.createMessage(MessageType.RESPONSE, Action.LOGIN_SUCCESS, responseEntity);
if (clientSession != null) {
clientSession.setPlayer(player);
clientSession.setPlayer(player);
clientSession.setStatus(PlayerStatus.ONLINE);
GameServerManager.getInstance().broadcastPlayerList();

}


} catch (HashingException ex) {
ServerInterruptException customException = new ServerInterruptException(ex.getStackTrace());
ExceptionHandlerMiddleware.getInstance().handleException(customException);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ public enum Action {
INVALID_OPPONENT(160),
NO_PENDING_REQUEST(170),
GET_AVAILABLE_PLAYERS(180),
USER_IS_ONLINE(190);
USER_IS_ONLINE(190),
GET_LEADERBOARD(200);


final int id;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ private void handleRequest(Message message , PlayerConnectionHandler sender) {

case REGISTER -> {
System.out.println("come reg");


AuthRequestEntity auth = gson.fromJson(message.getData(), AuthRequestEntity.class);

Expand All @@ -95,6 +96,10 @@ private void handleRequest(Message message , PlayerConnectionHandler sender) {
Message response = GameManager.getInstance().requestGame(requestInfo, sender, target);
sender.sendMessageToPlayer(gson.toJson(response));

}
case GET_LEADERBOARD -> {
Message response = server.getLeaderboardMessage();
sender.sendMessageToPlayer(gson.toJson(response));
}


Expand All @@ -111,10 +116,12 @@ private void handleResponse(Message msg, PlayerConnectionHandler sender) throws
switch (action) {

case GAME_RESPONSE -> {

GameResponseInfo requestInfo = gson.fromJson(msg.getData(), GameResponseInfo.class);
response = GameManager.getInstance().handleGameResponse(requestInfo, sender);
sender.sendMessageToPlayer(gson.toJson(response));
}
if (response != null) {
sender.sendMessageToPlayer(gson.toJson(response));
} }

case SEND_GAME_UPDATE -> {
MoveInfo moveInfo = gson.fromJson(msg.getData(), MoveInfo.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ public Message handleGameResponse(GameResponseInfo requestInfo, PlayerConnection
responder.setStatus(PlayerStatus.ONLINE);
GameServerManager.getInstance().broadcastPlayerList();

return Message.createMessage(MessageType.RESPONSE, Action.GAME_RESPONSE, requestInfo);
Message refusalMsg = Message.createMessage(MessageType.RESPONSE, Action.GAME_RESPONSE, requestInfo);

requester.sendMessageToPlayer(gson.toJson(refusalMsg));

return null;
}

return startGame(requester, responder);
Expand Down Expand Up @@ -202,7 +206,6 @@ public Message forwardMove(MoveInfo moveInfo) {
if (opponent == null) {
return Message.createMessage(MessageType.ERROR, Action.INVALID_OPPONENT, moveInfo);
}

Message msg = Message.createMessage(MessageType.RESPONSE, Action.SEND_GAME_UPDATE, moveInfo);
opponent.sendMessageToPlayer(gson.toJson(msg));

Expand All @@ -215,6 +218,74 @@ public Message forwardMove(MoveInfo moveInfo) {
}
}

public void handlePlayerDisconnect(PlayerConnectionHandler disconnectedPlayer) {
if (disconnectedPlayer == null) return;

System.out.println("Handling disconnect for: " +
(disconnectedPlayer.getPlayer() != null ? disconnectedPlayer.getPlayer().getUsername() : "Unknown"));


GameRequest foundRequest = null;
synchronized (lock) {
for (GameRequest req : pendingRequests) {
if (req.requester.equals(disconnectedPlayer) || req.target.equals(disconnectedPlayer)) {
foundRequest = req;
break;
}
}
if (foundRequest != null) {
pendingRequests.remove(foundRequest);
}
}

if (foundRequest != null) {
PlayerConnectionHandler opponent = (foundRequest.requester.equals(disconnectedPlayer))
? foundRequest.target
: foundRequest.requester;

opponent.setStatus(PlayerStatus.ONLINE);
GameServerManager.getInstance().broadcastPlayerList();

try {

Message msg = Message.createMessage(MessageType.ERROR, Action.INVALID_OPPONENT, null);
opponent.sendMessageToPlayer(gson.toJson(msg));
} catch (Exception e) {
System.out.println("Failed to notify opponent of pending disconnect: " + e.getMessage());
}
}


GameRoom foundRoom = null;
synchronized (lock) {
for (GameRoom room : activeRooms) {
if (room.getPlayer1().equals(disconnectedPlayer) || room.getPlayer2().equals(disconnectedPlayer)) {
foundRoom = room;
break;
}
}
if (foundRoom != null) {
activeRooms.remove(foundRoom);
}
}

if (foundRoom != null) {
PlayerConnectionHandler survivor = (foundRoom.getPlayer1().equals(disconnectedPlayer))
? foundRoom.getPlayer2()
: foundRoom.getPlayer1();

survivor.setStatus(PlayerStatus.ONLINE);
GameServerManager.getInstance().broadcastPlayerList();

try {
Message msg = Message.createMessage(MessageType.ERROR, Action.INVALID_OPPONENT, null);
survivor.sendMessageToPlayer(gson.toJson(msg));
} catch (Exception e) {
System.out.println("Failed to notify survivor of game disconnect: " + e.getMessage());
}
}
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class MoveInfo {
private final String roomId;
private final String playerId;
private final Object move;


public MoveInfo(String playerId, Object move, String roomId) {
this.playerId = playerId;
Expand Down