package server; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketException; import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import network.PacketHandler; import network.SocketReader; import network.protocol.Packet; import network.protocol.packets.ChatMessagePacket; import network.protocol.packets.SendChatMessagePacket; public class Server implements PacketHandler { private final DatagramSocket serverSocket; private final Map connexions; private final SocketReader reader; private final Map> roomNames; public Server(int port) throws SocketException { this.serverSocket = new DatagramSocket(port); this.connexions = new HashMap<>(); this.reader = new SocketReader(serverSocket, this); this.roomNames = new HashMap<>(); } public ArrayList getRoomNames() { return roomNames.keySet().stream().collect(ArrayList::new, ArrayList::add, ArrayList::addAll); } public String getRoomName(ServerConnexion connexion) { for (Map.Entry> entry : roomNames.entrySet()) { if(entry.getValue().contains(connexion)) { return entry.getKey(); } } return null; } public void createRoom(String roomName, ServerConnexion connexion) throws SocketException { if(roomNames.containsKey(roomName)) { throw new SocketException("Room already exists"); } roomNames.put(roomName, new ArrayList<>()); roomNames.get(roomName).add(connexion); } public void leaveRoom(ServerConnexion connexion) throws SocketException { String roomName = getRoomName(connexion); if(roomName != null) { roomNames.get(roomName).remove(connexion); // Remove the room if it is empty if(roomNames.get(roomName).isEmpty()) { roomNames.remove(roomName); } return; } throw new SocketException("Room does not exist"); } public void joinRoom(String roomName, ServerConnexion connexion) throws SocketException { if(roomNames.containsKey(roomName) && !roomNames.get(roomName).contains(connexion)) { roomNames.get(roomName).add(connexion); return; } throw new SocketException("Room does not exist"); } public void sendToRoom(ServerConnexion connexion, SendChatMessagePacket packet) throws SocketException { String roomName = getRoomName(connexion); ChatMessagePacket chatPacket = new ChatMessagePacket(Instant.now(), connexion.getChatterName(), packet.getContent()); if(roomName != null && roomNames.containsKey(roomName)) { roomNames.get(roomName).forEach(con -> con.sendPacket(chatPacket)); return; } throw new SocketException("You are not in a room or the room does not exist"); } public void close() { this.reader.stop(); } public boolean hasChatterName(String pseudo) { return this.connexions.values().stream() .anyMatch(connexion -> pseudo.equals(connexion.getChatterName())); } @Override public void handlePacket(Packet packet, InetSocketAddress address) { if (!connexions.containsKey(address)) { this.connexions.put(address, new ServerConnexion(this, serverSocket, address)); } this.connexions.get(address).visit(packet); } }