aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ch/epfl/xblast/ArgumentChecker.java29
-rw-r--r--src/ch/epfl/xblast/Lists.java39
-rw-r--r--src/ch/epfl/xblast/PlayerAction.java32
-rw-r--r--src/ch/epfl/xblast/PlayerID.java11
-rw-r--r--src/ch/epfl/xblast/Time.java13
-rw-r--r--src/ch/epfl/xblast/client/Client.java360
-rw-r--r--src/ch/epfl/xblast/client/GameState.java2
-rw-r--r--src/ch/epfl/xblast/client/KeyboardEventHandler.java29
-rw-r--r--src/ch/epfl/xblast/client/Main.java28
-rw-r--r--src/ch/epfl/xblast/client/XBlastComponent.java103
-rw-r--r--src/ch/epfl/xblast/server/Bonus.java2
-rw-r--r--src/ch/epfl/xblast/server/GameState.java18
-rw-r--r--src/ch/epfl/xblast/server/GameStateTransitioner.java2
-rw-r--r--src/ch/epfl/xblast/server/Main.java29
-rw-r--r--src/ch/epfl/xblast/server/Server.java341
-rw-r--r--src/ch/epfl/xblast/server/painter/PlayerPainter.java42
-rw-r--r--test/ch/epfl/xblast/client/PlayerTest.java40
-rw-r--r--test/ch/epfl/xblast/simulation/GraphicalSimulation.java19
18 files changed, 1102 insertions, 37 deletions
diff --git a/src/ch/epfl/xblast/ArgumentChecker.java b/src/ch/epfl/xblast/ArgumentChecker.java
index 7e77b61..56f8acd 100644
--- a/src/ch/epfl/xblast/ArgumentChecker.java
+++ b/src/ch/epfl/xblast/ArgumentChecker.java
@@ -59,4 +59,33 @@ public final class ArgumentChecker {
59 return s; 59 return s;
60 } 60 }
61 61
62 /**
63 * Returns the element from the array at the requested index, or null if it cannot be retrieved.
64 *
65 * @param array the array
66 * @param index the index
67 * @param <T> the type of element
68 * @return the requested element, or null
69 */
70 public static <T> T getOrNull(T[] array, int index) {
71 if (Objects.isNull(array) || index < 0 || index >= array.length)
72 return null;
73 else
74 return array[index];
75 }
76
77 /**
78 * Parses and returns an integer, or return null on error.
79 *
80 * @param str the integer to parse
81 * @return the parsed integer, or null
82 */
83 public static Integer parseIntOrNull(String str) {
84 try {
85 return Integer.parseInt(str);
86 } catch (NumberFormatException | NullPointerException e) {
87 return null;
88 }
89 }
90
62} 91}
diff --git a/src/ch/epfl/xblast/Lists.java b/src/ch/epfl/xblast/Lists.java
index 777fab2..9bd527b 100644
--- a/src/ch/epfl/xblast/Lists.java
+++ b/src/ch/epfl/xblast/Lists.java
@@ -2,7 +2,6 @@ package ch.epfl.xblast;
2 2
3import java.util.*; 3import java.util.*;
4import java.util.stream.Collectors; 4import java.util.stream.Collectors;
5import java.util.stream.IntStream;
6import java.util.stream.Stream; 5import java.util.stream.Stream;
7 6
8/** 7/**
@@ -207,10 +206,36 @@ public final class Lists {
207 if (Objects.isNull(kl) || Objects.isNull(vl) || kl.size() != vl.size()) 206 if (Objects.isNull(kl) || Objects.isNull(vl) || kl.size() != vl.size())
208 throw new IllegalArgumentException(); 207 throw new IllegalArgumentException();
209 208
210 return Collections.unmodifiableMap(IntStream 209 Map<K, V> m = new HashMap<>();
211 .range(0, kl.size()).mapToObj(i -> i) 210 Iterator<K> ki = kl.iterator();
212 .filter(i -> Objects.nonNull(vl.get(i))) 211 Iterator<V> vi = vl.iterator();
213 .collect(Collectors.toMap(kl::get, vl::get))); 212
213 while (ki.hasNext() && vi.hasNext())
214 m.put(ki.next(), vi.next());
215
216 return Collections.unmodifiableMap(m);
217 }
218
219 /**
220 * Maps linearly two lists, adjusting their respective size by truncating the key list or completing the value list
221 * with null values.
222 *
223 * @param kl the keys list
224 * @param vl the values list
225 * @param <K> the key type
226 * @param <V> the value type
227 * @return the map
228 */
229 public static <K, V> Map<K, V> linearAdjustedMap(List<K> kl, List<V> vl) {
230 if (Objects.isNull(kl) || Objects.isNull(vl))
231 throw new IllegalArgumentException();
232
233 if (kl.size() <= vl.size())
234 return Lists.linearMap(kl, vl.subList(0, kl.size()));
235 else
236 return Lists.linearMap(
237 kl,
238 concatenated(Arrays.asList(vl, Collections.nCopies(kl.size() - vl.size(), null))));
214 } 239 }
215 240
216 /** 241 /**
@@ -225,6 +250,8 @@ public final class Lists {
225 */ 250 */
226 public static <K, IK, V> Map<K, V> traverseMaps(Map<K, IK> m1, Map<IK, V> m2) { 251 public static <K, IK, V> Map<K, V> traverseMaps(Map<K, IK> m1, Map<IK, V> m2) {
227 return Collections.unmodifiableMap(m1.entrySet().stream() 252 return Collections.unmodifiableMap(m1.entrySet().stream()
253 .filter(e -> Objects.nonNull(e.getValue()))
254 .filter(e -> Objects.nonNull(m2.get(e.getValue())))
228 .collect(Collectors.toMap(Map.Entry::getKey, e -> m2.get(e.getValue())))); 255 .collect(Collectors.toMap(Map.Entry::getKey, e -> m2.get(e.getValue()))));
229 } 256 }
230 257
@@ -238,6 +265,8 @@ public final class Lists {
238 */ 265 */
239 public static <K, V> Map<K, V> invertMap(Map<V, K> m) { 266 public static <K, V> Map<K, V> invertMap(Map<V, K> m) {
240 return Collections.unmodifiableMap(m.entrySet().stream() 267 return Collections.unmodifiableMap(m.entrySet().stream()
268 .filter(e -> Objects.nonNull(e.getKey()))
269 .filter(e -> Objects.nonNull(e.getValue()))
241 .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey))); 270 .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)));
242 } 271 }
243 272
diff --git a/src/ch/epfl/xblast/PlayerAction.java b/src/ch/epfl/xblast/PlayerAction.java
index 703bc9d..6ce12ba 100644
--- a/src/ch/epfl/xblast/PlayerAction.java
+++ b/src/ch/epfl/xblast/PlayerAction.java
@@ -1,5 +1,7 @@
1package ch.epfl.xblast; 1package ch.epfl.xblast;
2 2
3import java.util.Optional;
4
3/** 5/**
4 * The player action enum. 6 * The player action enum.
5 * 7 *
@@ -14,6 +16,34 @@ public enum PlayerAction {
14 MOVE_S, 16 MOVE_S,
15 MOVE_W, 17 MOVE_W,
16 STOP, 18 STOP,
17 DROP_BOMB 19 DROP_BOMB;
20
21 public static PlayerAction fromByte(byte b) {
22 if ((int) b < 0 || (int) b >= PlayerAction.values().length)
23 throw new IllegalArgumentException();
24
25 return PlayerAction.values()[(int) b];
26 }
27
28 public byte toByte() {
29 return (byte) this.ordinal();
30 }
31
32 public Optional<Direction> associatedSpeedChangeEvent() {
33 switch (this) {
34 case MOVE_N:
35 return Optional.of(Direction.N);
36 case MOVE_E:
37 return Optional.of(Direction.E);
38 case MOVE_S:
39 return Optional.of(Direction.S);
40 case MOVE_W:
41 return Optional.of(Direction.W);
42 case STOP:
43 return Optional.empty();
44 default:
45 return null;
46 }
47 }
18 48
19} 49}
diff --git a/src/ch/epfl/xblast/PlayerID.java b/src/ch/epfl/xblast/PlayerID.java
index 9377fdf..72a48b9 100644
--- a/src/ch/epfl/xblast/PlayerID.java
+++ b/src/ch/epfl/xblast/PlayerID.java
@@ -28,4 +28,15 @@ public enum PlayerID {
28 } 28 }
29 } 29 }
30 30
31 public static PlayerID fromByte(byte b) {
32 if ((int) b < 0 || (int) b >= PlayerAction.values().length)
33 throw new IllegalArgumentException();
34
35 return PlayerID.values()[(int) b];
36 }
37
38 public byte toByte() {
39 return (byte) this.ordinal();
40 }
41
31} 42}
diff --git a/src/ch/epfl/xblast/Time.java b/src/ch/epfl/xblast/Time.java
index 7c84257..c53f1ef 100644
--- a/src/ch/epfl/xblast/Time.java
+++ b/src/ch/epfl/xblast/Time.java
@@ -28,4 +28,17 @@ public interface Time {
28 */ 28 */
29 int NS_PER_S = 1000 * US_PER_S; 29 int NS_PER_S = 1000 * US_PER_S;
30 30
31 /**
32 * Pauses the current thread for the given duration.
33 *
34 * @param ns the sleep duration (ns)
35 */
36 static void sleep(long ns) {
37 try {
38 Thread.sleep((long) (ns / 1E6), (int) (ns % 1E6));
39 } catch (InterruptedException e) {
40 Thread.currentThread().interrupt();
41 }
42 }
43
31} 44}
diff --git a/src/ch/epfl/xblast/client/Client.java b/src/ch/epfl/xblast/client/Client.java
new file mode 100644
index 0000000..24ca727
--- /dev/null
+++ b/src/ch/epfl/xblast/client/Client.java
@@ -0,0 +1,360 @@
1package ch.epfl.xblast.client;
2
3import ch.epfl.xblast.Lists;
4import ch.epfl.xblast.PlayerAction;
5import ch.epfl.xblast.PlayerID;
6import ch.epfl.xblast.Time;
7import ch.epfl.xblast.server.Server;
8
9import javax.swing.*;