From 1ab03f95d9dc7dd25a775dd17e1f3977bb987dd2 Mon Sep 17 00:00:00 2001 From: Timothée Floure Date: Fri, 20 May 2016 13:25:42 +0200 Subject: Improve the documentation for the server package --- src/ch/epfl/xblast/server/Main.java | 5 ++ src/ch/epfl/xblast/server/Server.java | 125 +++++++++++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 2 deletions(-) diff --git a/src/ch/epfl/xblast/server/Main.java b/src/ch/epfl/xblast/server/Main.java index 98bbb3d..aff499b 100644 --- a/src/ch/epfl/xblast/server/Main.java +++ b/src/ch/epfl/xblast/server/Main.java @@ -13,6 +13,11 @@ public final class Main { // Static class } + /** + * Starts a new server. + * + * @param args arguments given to the server (i.e. number of players required for the game to start) + */ public static void main(String[] args) { Integer expectedClients = ArgumentChecker.parseIntOrNull(ArgumentChecker.getOrNull(args, 0)); String iface = ArgumentChecker.getOrNull(args, 1); diff --git a/src/ch/epfl/xblast/server/Server.java b/src/ch/epfl/xblast/server/Server.java index 8a4b09b..015d771 100644 --- a/src/ch/epfl/xblast/server/Server.java +++ b/src/ch/epfl/xblast/server/Server.java @@ -21,14 +21,29 @@ import java.util.*; */ public class Server { - public static final int DEFAULT_PORT = 2016; + /** + * Default parameters of the server. + */ private static final long REFRESH_RATE = (long) (50 * 1E6); // nanosecond - private static final int DEFAULT_EXPECTED_CLIENTS = PlayerID.values().length; + public static final int DEFAULT_PORT = 2016; + + /** + * ID of an observer. + */ public static final byte OBSERVER = -1; + /** + * A Channel. + */ private static class Channel { + /** + * Transform a list of bytes to an array of bytes. + * + * @param l the given list of bytes + * @return the array built from the given list + */ private static byte[] toByteArray(List l) { byte[] arr = new byte[l.size()]; @@ -38,6 +53,13 @@ public class Server { return arr; } + /** + * Create the socket which will be listened. + * + * @param host hostname + * @param port port to be listened + * @return the socket build from the given params + */ private static InetSocketAddress listeningInterface(String host, int port) { if (Objects.isNull(host)) return new InetSocketAddress(port); @@ -45,6 +67,12 @@ public class Server { return new InetSocketAddress(host, port); } + /** + * Open a UDP channel. + * + * @param iface listened socket + * @return a UDP channel + */ private static DatagramChannel openChannel(InetSocketAddress iface) { try { DatagramChannel chan = DatagramChannel.open(StandardProtocolFamily.INET); @@ -57,16 +85,33 @@ public class Server { } } + /** + * The UDP communication channel. + */ private final DatagramChannel channel; + /** + * Instantiates a new Channel. + * + * @param iface listened socket + */ Channel(InetSocketAddress iface) { this.channel = openChannel(iface); } + /** + * Instantiates a new Channel. + * + * @param host hostname + * @param port port to be listened + */ Channel(String host, Integer port) { this(listeningInterface(host, Optional.ofNullable(port).orElse(DEFAULT_PORT))); } + /** + * Close the channel. + */ void closeChannel() { try { this.channel.close(); @@ -75,6 +120,12 @@ public class Server { } } + /** + * Accept the registration of a new client. + * + * @param registrations + * @return a list of the clients. + */ List acceptRegistrations(int registrations) { List clients = new ArrayList<>(registrations); @@ -87,6 +138,11 @@ public class Server { return Collections.unmodifiableList(clients); } + /** + * Collect actions from the players. + * + * @return a list map containing the actions related to each player + */ Map collectActions() { Map actions = new HashMap<>(); Optional> action; @@ -100,6 +156,12 @@ public class Server { return Collections.unmodifiableMap(actions); } + /** + * Send data through the socket. + * + * @param content data to be send + * @param dst recepient of the data + */ void send(List content, SocketAddress dst) { try { ByteBuffer buf = ByteBuffer.wrap(toByteArray(content)); @@ -109,6 +171,12 @@ public class Server { } } + /** + * Receive a Byte from the socket. + * + * @param block + * @return an Optional containing the received data + */ private Optional> receiveByte(boolean block) { try { ByteBuffer buf = ByteBuffer.allocate(1); @@ -124,6 +192,12 @@ public class Server { } } + /** + * Receive a player action from the socket. + * + * @param block + * @return an Optional containing the received player action + */ private Optional> receiveAction(boolean block) { try { Map.Entry actionByte = this.receiveByte(block).get(); @@ -134,6 +208,11 @@ public class Server { } } + /** + * Accept an action from the socket. + * + * @return the accepted action + */ private Map.Entry acceptAction() { Optional> action; @@ -144,6 +223,11 @@ public class Server { return action.get(); } + /** + * Accept the registration of a player + * + * @return the address of the new player + */ private SocketAddress acceptRegistration() { Map.Entry clientAction; @@ -156,29 +240,55 @@ public class Server { } + /** + * The communication channel. + */ private final Channel channel; + + /** + * Required number of player to start a game (up to 4). + */ private final int expectedClients; + /** + * Maps of the players and their addresses. + */ private Map registeredClientsMap; private Map playersAddressMap; + /** + * Instantiates a new server. + * + * @param iface the interface to be listened + * @param port the port to be listened + * @param expectedClients required number of player to start a game + */ public Server(String iface, Integer port, Integer expectedClients) { this.channel = new Channel(iface, port); this.expectedClients = Optional.ofNullable(expectedClients).orElse(DEFAULT_EXPECTED_CLIENTS); } + /** + * Run the whole server. + */ public void run() { this.acceptClientRegistrations(); this.runGame(); this.channel.closeChannel(); } + /** + * Handle the registration of new clients. + */ private void acceptClientRegistrations() { List clients = this.channel.acceptRegistrations(this.expectedClients); this.registeredClientsMap = Lists.linearAdjustedMap(clients, Arrays.asList(PlayerID.values())); this.playersAddressMap = Lists.invertMap(this.registeredClientsMap); } + /** + * Launch the Game. + */ private void runGame() { GameState gameState = GameState.DEFAULT_GAME_STATE; @@ -190,11 +300,22 @@ public class Server { } } + /** + * Update the given GameState to the next tick. + * + * @param gs the given GameState + * @return the updated GameState + */ private GameState updateGameState(GameState gs) { Map events = Lists.traverseMaps(this.playersAddressMap, this.channel.collectActions()); return gs.next(events); } + /** + * Send the GameState to every player. + * + * @param gs the GameState to be send. + */ private void broadcastGameState(GameState gs) { List serialized = GameStateSerializer.serialize(BoardPainter.DEFAULT_BOARD_PAINTER, gs); -- cgit v1.2.3