diff options
-rw-r--r-- | src/ch/epfl/xblast/client/Client.java | 131 | ||||
-rw-r--r-- | src/ch/epfl/xblast/client/Main.java | 5 | ||||
-rw-r--r-- | src/ch/epfl/xblast/client/XBlastComponent.java | 96 |
3 files changed, 232 insertions, 0 deletions
diff --git a/src/ch/epfl/xblast/client/Client.java b/src/ch/epfl/xblast/client/Client.java index b522312..8ccea00 100644 --- a/src/ch/epfl/xblast/client/Client.java +++ b/src/ch/epfl/xblast/client/Client.java | |||
@@ -26,13 +26,25 @@ import java.util.function.Consumer; | |||
26 | */ | 26 | */ |
27 | public class Client { | 27 | public class Client { |
28 | 28 | ||
29 | /** | ||
30 | * Client's parameters. | ||
31 | */ | ||
29 | private static final String DEFAULT_SERVER_HOST = "localhost"; | 32 | private static final String DEFAULT_SERVER_HOST = "localhost"; |
30 | private static final int DEFAULT_SERVER_PORT = Server.DEFAULT_PORT; | 33 | private static final int DEFAULT_SERVER_PORT = Server.DEFAULT_PORT; |
31 | private static final int PACKET_MAX_SIZE = 1000; | 34 | private static final int PACKET_MAX_SIZE = 1000; |
32 | private static final long REGISTER_PING_INTERVAL = 1 * Time.NS_PER_S; // ns | 35 | private static final long REGISTER_PING_INTERVAL = 1 * Time.NS_PER_S; // ns |
33 | 36 | ||
37 | /** | ||
38 | * Communication channel. | ||
39 | */ | ||
34 | private static class Channel { | 40 | private static class Channel { |
35 | 41 | ||
42 | /** | ||
43 | * Transform a buffer to a list of bytes. | ||
44 | * | ||
45 | * @param buf given buffer | ||
46 | * @return the list of bytes built from the given buffer | ||
47 | */ | ||
36 | private static List<Byte> bufferToList(ByteBuffer buf) { | 48 | private static List<Byte> bufferToList(ByteBuffer buf) { |
37 | List<Byte> l = new ArrayList<>(buf.remaining()); | 49 | List<Byte> l = new ArrayList<>(buf.remaining()); |
38 | 50 | ||
@@ -42,6 +54,11 @@ public class Client { | |||
42 | return Collections.unmodifiableList(l); | 54 | return Collections.unmodifiableList(l); |
43 | } | 55 | } |
44 | 56 | ||
57 | /** | ||
58 | * Create the UDP communication Channel. | ||
59 | * | ||
60 | * @return the UDP communication Channel | ||
61 | */ | ||
45 | private static DatagramChannel openChannel() { | 62 | private static DatagramChannel openChannel() { |
46 | try { | 63 | try { |
47 | return DatagramChannel.open(StandardProtocolFamily.INET); | 64 | return DatagramChannel.open(StandardProtocolFamily.INET); |
@@ -52,20 +69,37 @@ public class Client { | |||
52 | } | 69 | } |
53 | } | 70 | } |
54 | 71 | ||
72 | /** | ||
73 | * Parameters of the Channel. | ||
74 | */ | ||
55 | private final SocketAddress serverAddr; | 75 | private final SocketAddress serverAddr; |
56 | private final DatagramChannel channel; | 76 | private final DatagramChannel channel; |
57 | 77 | ||
78 | /** | ||
79 | * Instantiates a new Channel. | ||
80 | * | ||
81 | * @param iface socket | ||
82 | */ | ||
58 | Channel(InetSocketAddress iface) { | 83 | Channel(InetSocketAddress iface) { |
59 | this.serverAddr = iface; | 84 | this.serverAddr = iface; |
60 | this.channel = openChannel(); | 85 | this.channel = openChannel(); |
61 | } | 86 | } |
62 | 87 | ||
88 | /** | ||
89 | * Instantiates a new Channel. | ||
90 | * | ||
91 | * @param host hostname | ||
92 | * @param port port | ||
93 | */ | ||
63 | Channel(String host, Integer port) { | 94 | Channel(String host, Integer port) { |
64 | this(new InetSocketAddress( | 95 | this(new InetSocketAddress( |
65 | Optional.ofNullable(host).orElse(DEFAULT_SERVER_HOST), | 96 | Optional.ofNullable(host).orElse(DEFAULT_SERVER_HOST), |
66 | Optional.ofNullable(port).orElse(DEFAULT_SERVER_PORT))); | 97 | Optional.ofNullable(port).orElse(DEFAULT_SERVER_PORT))); |
67 | } | 98 | } |
68 | 99 | ||
100 | /** | ||
101 | * Close the Channel. | ||
102 | */ | ||
69 | void closeChannel() { | 103 | void closeChannel() { |
70 | try { | 104 | try { |
71 | this.channel.close(); | 105 | this.channel.close(); |
@@ -74,10 +108,21 @@ public class Client { | |||
74 | } | 108 | } |
75 | } | 109 | } |
76 | 110 | ||
111 | /** | ||
112 | * Send an action through the Channel. | ||
113 | * | ||
114 | * @param action action to send | ||
115 | */ | ||
77 | void sendAction(PlayerAction action) { | 116 | void sendAction(PlayerAction action) { |
78 | this.sendByte(action.toByte()); | 117 | this.sendByte(action.toByte()); |
79 | } | 118 | } |
80 | 119 | ||
120 | /** | ||
121 | * Receive a GameState through the Channel. | ||
122 | * | ||
123 | * @param block | ||
124 | * @return the received GameState | ||
125 | */ | ||
81 | List<Byte> receiveGameState(boolean block) { | 126 | List<Byte> receiveGameState(boolean block) { |
82 | Optional<List<Byte>> state; | 127 | Optional<List<Byte>> state; |
83 | 128 | ||
@@ -88,10 +133,20 @@ public class Client { | |||
88 | return state.get(); | 133 | return state.get(); |
89 | } | 134 | } |
90 | 135 | ||
136 | /** | ||
137 | * Send a byte through the Channel. | ||
138 | * | ||
139 | * @param b byte to send | ||
140 | */ | ||
91 | private void sendByte(byte b) { | 141 | private void sendByte(byte b) { |
92 | this.send(ByteBuffer.wrap(new byte[]{b})); | 142 | this.send(ByteBuffer.wrap(new byte[]{b})); |
93 | } | 143 | } |
94 | 144 | ||
145 | /** | ||
146 | * Send the content of a buffer. | ||
147 | * | ||
148 | * @param b buffer containing the bytes to send | ||
149 | */ | ||
95 | private void send(ByteBuffer b) { | 150 | private void send(ByteBuffer b) { |
96 | try { | 151 | try { |
97 | this.channel.send(b, this.serverAddr); | 152 | this.channel.send(b, this.serverAddr); |
@@ -100,6 +155,12 @@ public class Client { | |||
100 | } | 155 | } |
101 | } | 156 | } |
102 | 157 | ||
158 | /** | ||
159 | * Receive data from the Channel. | ||
160 | * | ||
161 | * @param block | ||
162 | * @return the received data | ||
163 | */ | ||
103 | private Optional<List<Byte>> receive(boolean block) { | 164 | private Optional<List<Byte>> receive(boolean block) { |
104 | try { | 165 | try { |
105 | ByteBuffer buf = ByteBuffer.allocate(PACKET_MAX_SIZE); | 166 | ByteBuffer buf = ByteBuffer.allocate(PACKET_MAX_SIZE); |
@@ -115,8 +176,17 @@ public class Client { | |||
115 | 176 | ||
116 | } | 177 | } |
117 | 178 | ||
179 | /** | ||
180 | * The Graphical User Interface. | ||
181 | */ | ||
118 | private static class GUI { | 182 | private static class GUI { |
119 | 183 | ||
184 | /** | ||
185 | * Build the window. | ||
186 | * | ||
187 | * @param content content of the window | ||
188 | * @return the frame | ||
189 | */ | ||
120 | private static JFrame buildFrame(Container content) { | 190 | private static JFrame buildFrame(Container content) { |
121 | JFrame frame = new JFrame(); | 191 | JFrame frame = new JFrame(); |
122 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | 192 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
@@ -128,30 +198,58 @@ public class Client { | |||
128 | return frame; | 198 | return frame; |
129 | } | 199 | } |
130 | 200 | ||
201 | /** | ||
202 | * Attach the keyboard events handler to the component. | ||
203 | * @param comp component | ||
204 | * @param actionConsumer actionConsumer corresponding to the keyboardEventHandler | ||
205 | */ | ||
131 | private static void attachKeyboardHandler(Component comp, Consumer<PlayerAction> actionConsumer) { | 206 | private static void attachKeyboardHandler(Component comp, Consumer<PlayerAction> actionConsumer) { |
132 | comp.addKeyListener(new KeyboardEventHandler(actionConsumer)); | 207 | comp.addKeyListener(new KeyboardEventHandler(actionConsumer)); |
133 | comp.requestFocusInWindow(); | 208 | comp.requestFocusInWindow(); |
134 | } | 209 | } |
135 | 210 | ||
211 | /** | ||
212 | * GUI's parameters. | ||
213 | */ | ||
136 | private final XBlastComponent gameComponent; | 214 | private final XBlastComponent gameComponent; |
137 | private final Consumer<PlayerAction> actionConsumer; | 215 | private final Consumer<PlayerAction> actionConsumer; |
138 | 216 | ||
217 | /** | ||
218 | * Instantiates a new GUI. | ||
219 | * | ||
220 | * @param actionConsumer actionConsumer corresponding to the keyboardEventHandler | ||
221 | */ | ||
139 | GUI(Consumer<PlayerAction> actionConsumer) { | 222 | GUI(Consumer<PlayerAction> actionConsumer) { |
140 | this.gameComponent = new XBlastComponent(); | 223 | this.gameComponent = new XBlastComponent(); |
141 | this.actionConsumer = actionConsumer; | 224 | this.actionConsumer = actionConsumer; |
142 | } | 225 | } |
143 | 226 | ||
227 | /** | ||
228 | * Build and display the GUI. | ||
229 | */ | ||
144 | public void display() { | 230 | public void display() { |
145 | buildFrame(this.gameComponent); | 231 | buildFrame(this.gameComponent); |
146 | attachKeyboardHandler(this.gameComponent, this.actionConsumer); | 232 | attachKeyboardHandler(this.gameComponent, this.actionConsumer); |
147 | } | 233 | } |
148 | 234 | ||
235 | /** | ||
236 | * Update the displayed GameState. | ||
237 | * | ||
238 | * @param gs new GameState to be displayed | ||