aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ch/epfl/xblast/client/GameStateDeserializer.java185
1 files changed, 185 insertions, 0 deletions
diff --git a/src/ch/epfl/xblast/client/GameStateDeserializer.java b/src/ch/epfl/xblast/client/GameStateDeserializer.java
new file mode 100644
index 0000000..f95c515
--- /dev/null
+++ b/src/ch/epfl/xblast/client/GameStateDeserializer.java
@@ -0,0 +1,185 @@
1package ch.epfl.xblast.client;
2
3import ch.epfl.xblast.PlayerID;
4import ch.epfl.xblast.RunLengthEncoder;
5import ch.epfl.xblast.SubCell;
6import ch.epfl.xblast.client.GameState.Player;
7import ch.epfl.xblast.server.Ticks;
8
9import java.util.ArrayList;
10import java.util.List;
11import java.awt.Image;
12import java.util.stream.Collectors;
13
14/**
15 * @author Timothée FLOURE (257420)
16 */
17public final class GameStateDeserializer {
18 /**
19 * Image collections folders
20 */
21 private final static String BOARD_IMAGES_FOLDER = "block";
22 private final static String EXPLOSION_IMAGES_FOLDER = "explosion";
23 private final static String PLAYER_IMAGES_FOLDER = "player";
24 private final static String TIME_IMAGES_FOLDER = "score";
25 private final static String SCORE_IMAGES_FOLDER = "score";
26
27 /**
28 * Serialized data chunks
29 */
30 private final static int NUMBER_OF_PLAYERS = 4;
31 private final static int PLAYER_CHUNK_SIZE = 6;
32 private final static int PLAYER_SIZE = NUMBER_OF_PLAYERS * PLAYER_CHUNK_SIZE;
33 private final static int TIME_LINE_SIZE = (Ticks.GAME_DURATION / 2);
34
35 /**
36 * Images ID
37 */
38 private final static int TIME_LINE_LED_ON_IMAGE_ID = 21;
39 private final static int TIME_LINE_LED_OFF_IMAGE_ID = 20;
40 private final static int SCORE_TEXT_MIDDLE_IMAGE_ID = 10;
41 private final static int SCORE_TEXT_RIGHT_IMAGE_ID = 11;
42 private final static int SCORE_TILE_VOID_IMAGE_ID = 12;
43
44 /**
45 * Deserialize an encoded chunk of data and link it to images.
46 *
47 * @param data serialized data
48 * @param imageCollection ImageCollection related to the type of data
49 * @return a list of Images corresponding to the serialized element
50 */
51 private static List<Image> deserializeChunk(List<Byte> data, ImageCollection imageCollection) {
52 return RunLengthEncoder.decode(data).stream()
53 .map(c -> imageCollection.imageOrNull(Byte.toUnsignedInt(c)))
54 .collect(Collectors.toList());
55 }
56
57 /**
58 * Build a list of players given the serialized data..
59 *
60 * @param serializedPlayers the serialized players
61 * @return a list of players built from the serialized players
62 */
63 private static List<Player> deserializePlayers(List<Byte> serializedPlayers) {
64 List<Player> players = new ArrayList<>();
65
66 for (int i = 0; i < NUMBER_OF_PLAYERS; i++) {
67 players.add(
68 deserializePlayer(
69 serializedPlayers.subList(i * PLAYER_CHUNK_SIZE, (i+1) * PLAYER_CHUNK_SIZE), i
70 )
71 );
72 }
73
74 return players;
75 }
76
77 /**
78 * Generate a Player from the serialized data.
79 *
80 * @param serializedPlayer a serialized player
81 * @return a player built from the serialized player
82 */
83 private static Player deserializePlayer(List<Byte> serializedPlayer, int i) {
84 PlayerID id = PlayerID.values()[i];
85 int lives = Byte.toUnsignedInt(serializedPlayer.get(0));
86 SubCell position = new SubCell(
87 Byte.toUnsignedInt(serializedPlayer.get(1)),
88 Byte.toUnsignedInt(serializedPlayer.get(2))
89 );
90 Image image = (new ImageCollection(PLAYER_IMAGES_FOLDER)).imageOrNull(Byte.toUnsignedInt(serializedPlayer.get(3)));
91
92 return new Player(id, lives, position, image);
93 }
94
95 /**
96 * Generate the list of images composing the scores.
97 *
98 * @param players players
99 * @return the scores of the given players
100 */
101 private static List<Image> buildScores(List<Player> players) {
102 List<Image> scores = new ArrayList<>();
103 ImageCollection imageCollection = new ImageCollection(SCORE_IMAGES_FOLDER);
104
105 scores.addAll(buildPlayerScore(players.get(0), imageCollection));
106
107 return scores;
108 }
109
110 /**
111 * Generate the images composing the score of one player.
112 *
113 * @param player serialized data corresponding to the player
114 * @param imageCollection image collection related to the scores
115 * @return the score of the given player
116 */
117 private static List<Image> buildPlayerScore(Player player, ImageCollection imageCollection) {
118 List<Image> playerScore = new ArrayList<>();
119
120 if (player.lives() < 1)
121 playerScore.add(imageCollection.imageOrNull(0 + (player.id().ordinal()*2)));
122 else
123 playerScore.add(imageCollection.imageOrNull(1 + (player.id().ordinal()*2)));
124
125 playerScore.add(imageCollection.imageOrNull(SCORE_TEXT_MIDDLE_IMAGE_ID));
126 playerScore.add(imageCollection.imageOrNull(SCORE_TEXT_RIGHT_IMAGE_ID));
127 return playerScore;
128 }
129 /**
130 * Generate the list of images composing the time "line".
131 *
132 * @param time the remaining time
133 * @return the list of images composing the time "line"
134 */
135 private static List<Image> buildTimeLine(Byte time) {
136 List<Image> ticks = new ArrayList<>();
137 ImageCollection imageCollection = new ImageCollection(TIME_IMAGES_FOLDER);
138
139 for (int i = 0; i < TIME_LINE_SIZE; i++) {
140 if (i < Byte.toUnsignedInt(time))
141 ticks.add(imageCollection.imageOrNull(TIME_LINE_LED_ON_IMAGE_ID));
142 else
143 ticks.add(imageCollection.imageOrNull(TIME_LINE_LED_OFF_IMAGE_ID));
144 }
145 return ticks;
146 }
147
148 /**
149 * Deserialize an incoming GameState.
150 *
151 * @param serializedData the serialized gameState
152 * @return a new GameState build from the serialized data.
153 */
154 public static GameState deserialize(List<Byte> serializedData) {
155
156 // Indexes
157 int boardIndex = 1;
158 int boardSize = serializedData.get(boardIndex);
159 int explosionsIndex = boardIndex + boardSize;
160 int explosionsSize = serializedData.get(explosionsIndex);
161 int playersIndex = explosionsIndex + explosionsSize;
162 Byte time = serializedData.get(serializedData.size());
163
164 // Deserialize the Board
165 List<Image> board = deserializeChunk(
166 serializedData.subList(boardIndex, boardSize),
167 new ImageCollection(BOARD_IMAGES_FOLDER)
168 );
169
170 // Deserialize the explosions
171 List<Image> explosions = deserializeChunk(
172 serializedData.subList(boardIndex,boardSize),
173 new ImageCollection(EXPLOSION_IMAGES_FOLDER)
174 );
175
176 // Deserialize the players
177 List<Player> players = deserializePlayers(serializedData.subList(playersIndex,PLAYER_SIZE));
178
179 // Generate the scores and the time "line"
180 List<Image> scores = buildScores(players);
181 List<Image> timeLine = buildTimeLine(time);
182
183 return new GameState(players, board, explosions, scores, timeLine);
184 }
185}