aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ch/epfl/xblast/server/Server.java177
1 files changed, 103 insertions, 74 deletions
diff --git a/src/ch/epfl/xblast/server/Server.java b/src/ch/epfl/xblast/server/Server.java
index 58f3c07..6d1d62f 100644
--- a/src/ch/epfl/xblast/server/Server.java
+++ b/src/ch/epfl/xblast/server/Server.java
@@ -22,119 +22,148 @@ public class Server {
22 public static final int DEFAULT_PORT = 2016; 22 public static final int DEFAULT_PORT = 2016;
23 private static final int DEFAULT_EXPECTED_CLIENTS = PlayerID.values().length; 23 private static final int DEFAULT_EXPECTED_CLIENTS = PlayerID.values().length;
24 24
25 private static InetSocketAddress listeningInterface(String host, int port) { 25 private static class Channel {
26 if (Objects.isNull(host))
27 return new InetSocketAddress(port);
28 else
29 return new InetSocketAddress(host, port);
30 }
31 26
32 private static DatagramChannel openChannel(InetSocketAddress iface) { 27 private static InetSocketAddress listeningInterface(String host, int port) {
33 try { 28 if (Objects.isNull(host))
34 DatagramChannel chan = DatagramChannel.open(StandardProtocolFamily.INET); 29 return new InetSocketAddress(port);
35 chan.bind(iface); 30 else
36 return chan; 31 return new InetSocketAddress(host, port);
37 } catch (IOException e) {
38 e.printStackTrace();
39 System.exit(1);
40 return null;
41 } 32 }
42 }
43 33
44 private static Optional<Map.Entry<SocketAddress, Byte>> receiveByte(DatagramChannel chan, boolean block) { 34 private static DatagramChannel openChannel(InetSocketAddress iface) {
45 try { 35 try {
46 ByteBuffer buf = ByteBuffer.allocate(1); 36 DatagramChannel chan = DatagramChannel.open(StandardProtocolFamily.INET);
47 chan.configureBlocking(block); 37 chan.bind(iface);
48 SocketAddress client = chan.receive(buf); 38 return chan;
39 } catch (IOException e) {
40 e.printStackTrace();
41 System.exit(1);
42 return null;
43 }
44 }
49 45
50 if (Objects.isNull(client) || buf.position() == 0) 46 private final DatagramChannel channel;
51 throw new IOException();
52 47
53 return Optional.of(new AbstractMap.SimpleImmutableEntry<>(client, buf.get(0))); 48 Channel(InetSocketAddress iface) {
54 } catch (IOException e) { 49 this.channel = openChannel(iface);
55 return Optional.empty();
56 } 50 }
57 }
58 51
59 private static Optional<Map.Entry<SocketAddress, PlayerAction>> receiveAction(DatagramChannel chan, boolean block) { 52 Channel(String host, Integer port) {
60 try { 53 this(listeningInterface(host, Optional.ofNullable(port).orElse(DEFAULT_PORT)));
61 Map.Entry<SocketAddress, Byte> actionByte = receiveByte(chan, block).get(); 54 }
62 PlayerAction playerAction = PlayerAction.fromByte(actionByte.getValue()); 55
63 return Optional.of(new AbstractMap.SimpleImmutableEntry<>(actionByte.getKey(), playerAction)); 56 void closeChannel() {
64 } catch (NoSuchElementException | IllegalArgumentException e) { 57 try {
65 return Optional.empty(); 58 this.channel.close();
59 } catch (IOException e) {
60 e.printStackTrace();
61 }
66 } 62 }
67 }
68 63
69 private static Map.Entry<SocketAddress, PlayerAction> acceptAction(DatagramChannel chan) { 64 List<SocketAddress> acceptRegistrations(int registrations) {
70 Optional<Map.Entry<SocketAddress, PlayerAction>> action; 65 List<SocketAddress> clients = new ArrayList<>(registrations);
71 66
72 do { 67 while (clients.size() < registrations) {
73 action = receiveAction(chan, true); 68 SocketAddress client = this.acceptRegistration();
74 } while (!action.isPresent()); 69 if (!clients.contains(client))
70 clients.add(client);
71 }
75 72
76 return action.get(); 73 return Collections.unmodifiableList(clients);
77 } 74 }
78 75
79 private static Map<SocketAddress, PlayerAction> collectActions(DatagramChannel chan) { 76 Map<SocketAddress, PlayerAction> collectActions() {
80 Map<SocketAddress, PlayerAction> actions = new HashMap<>(); 77 Map<SocketAddress, PlayerAction> actions = new HashMap<>();
81 Optional<Map.Entry<SocketAddress, PlayerAction>> action; 78 Optional<Map.Entry<SocketAddress, PlayerAction>> action;
82 79
83 while (true) { 80 while (true) {
84 action = receiveAction(chan, false); 81 action = this.receiveAction(false);
85 if (!action.isPresent()) break; 82 if (!action.isPresent()) break;
86 actions.put(action.get().getKey(), action.get().getValue()); 83 actions.put(action.get().getKey(), action.get().getValue());
84 }
85
86 return Collections.unmodifiableMap(actions);
87 } 87 }
88 88
89 return Collections.unmodifiableMap(actions); 89 private Optional<Map.Entry<SocketAddress, Byte>> receiveByte(boolean block) {
90 } 90 try {
91 ByteBuffer buf = ByteBuffer.allocate(1);
92 this.channel.configureBlocking(block);
93 SocketAddress client = this.channel.receive(buf);
91 94
92 private static SocketAddress acceptRegistration(DatagramChannel chan) { 95 if (Objects.isNull(client) || buf.position() == 0)
93 Map.Entry<SocketAddress, PlayerAction> clientAction; 96 throw new IOException();
94 97
95 do { 98 return Optional.of(new AbstractMap.SimpleImmutableEntry<>(client, buf.get(0)));
96 clientAction = acceptAction(chan); 99 } catch (IOException e) {
97 } while (clientAction.getValue() != PlayerAction.JOIN_GAME); 100 return Optional.empty();
101 }
102 }
98 103
99 return clientAction.getKey(); 104 private Optional<Map.Entry<SocketAddress, PlayerAction>> receiveAction(boolean block) {
100 } 105 try {
106 Map.Entry<SocketAddress, Byte> actionByte = this.receiveByte(block).get();
107 PlayerAction playerAction = PlayerAction.fromByte(actionByte.getValue());
108 return Optional.of(new AbstractMap.SimpleImmutableEntry<>(actionByte.getKey(), playerAction));
109 } catch (NoSuchElementException | IllegalArgumentException e) {
110 return Optional.empty();
111 }
112 }
113
114 private Map.Entry<SocketAddress, PlayerAction> acceptAction() {
115 Optional<Map.Entry<SocketAddress, PlayerAction>> action;
101 116
102 private static List<SocketAddress> acceptRegistrations(DatagramChannel chan, int registrations) { 117 do {
103 List<SocketAddress> clients = new ArrayList<>(registrations); 118 action = this.receiveAction(true);
119 } while (!action.isPresent());
104 120
105 while (clients.size() < registrations) { 121 return action.get();
106 SocketAddress client = acceptRegistration(chan); 122 }
107 if (!clients.contains(client)) 123
108 clients.add(client); 124 private SocketAddress acceptRegistration() {
125 Map.Entry<SocketAddress, PlayerAction> clientAction;
126
127 do {
128 clientAction = this.acceptAction();
129 } while (clientAction.getValue() != PlayerAction.JOIN_GAME);
130
131 return clientAction.getKey();
109 } 132 }
110 133
111 return Collections.unmodifiableList(clients);
112 } 134 }
113 135
114 private final InetSocketAddress iface; 136 private final Channel channel;
115 private final int expectedClients; 137 private final int expectedClients;
116 private Map<SocketAddress, PlayerID> registeredClients; 138
139 private Map<SocketAddress, PlayerID> registeredClientsMap;
140 private Map<PlayerID, SocketAddress> playersAddressMap;
117 141
118 public Server(String iface, Integer port, Integer expectedClients) { 142 public Server(String iface, Integer port, Integer expectedClients) {
119 this.iface = listeningInterface(iface, Optional.ofNullable(port).orElse(DEFAULT_PORT)); 143 this.channel = new Channel(iface, port);
120 this.expectedClients = Optional.ofNullable(expectedClients).orElse(DEFAULT_EXPECTED_CLIENTS); 144 this.expectedClients = Optional.ofNullable(expectedClients).orElse(DEFAULT_EXPECTED_CLIENTS);
121 } 145 }
122 146
123 public void run() { 147 public void run() {
124 DatagramChannel chan = openChannel(this.iface); 148 this.acceptClientRegistrations();
125 List<SocketAddress> clients = acceptRegistrations(chan, this.expectedClients); 149 this.runGame();
126 this.registeredClients = Lists.linearAdjustedMap(clients, Arrays.asList(PlayerID.values())); 150 this.channel.closeChannel();
151 }
127 152
128 System.out.println(this.registeredClients); 153 private void acceptClientRegistrations() {
154 List<SocketAddress> clients = this.channel.acceptRegistrations(this.expectedClients);
155 this.registeredClientsMap = Lists.linearAdjustedMap(clients, Arrays.asList(PlayerID.values()));
156 this.playersAddressMap = Lists.invertMap(this.registeredClientsMap);
157 }
129 158
159 private void runGame() {
130 try { 160 try {
131 Thread.sleep(10000); 161 Thread.sleep(10000);
132 } catch (InterruptedException e) { 162 } catch (InterruptedException e) {
133 e.printStackTrace(); 163 e.printStackTrace();
134 } 164 }
135 165
136 Map<SocketAddress, PlayerAction> actions = collectActions(chan); 166 Map<SocketAddress, PlayerAction> actions = this.channel.collectActions();