1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.magicproject.deckbuilder;
20
21 import java.awt.Component;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29
30 import javax.swing.JOptionPane;
31
32 import net.sf.magicproject.clickable.targetable.card.MCard;
33 import net.sf.magicproject.clickable.targetable.player.Player;
34 import net.sf.magicproject.database.DatabaseCard;
35 import net.sf.magicproject.database.DatabaseFactory;
36 import net.sf.magicproject.network.ConnectionManager;
37 import net.sf.magicproject.network.MInputStream;
38 import net.sf.magicproject.network.NetworkActor;
39 import net.sf.magicproject.token.IdPositions;
40 import net.sf.magicproject.tools.Log;
41 import net.sf.magicproject.tools.MCardCompare;
42 import net.sf.magicproject.tools.MToolKit;
43 import net.sf.magicproject.ui.MListModel;
44 import net.sf.magicproject.ui.MagicUIComponents;
45 import net.sf.magicproject.ui.component.LoaderConsole;
46 import net.sf.magicproject.ui.i18n.LanguageManager;
47 import net.sf.magicproject.zone.MZone;
48
49 /***
50 * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
51 * @since 0.90
52 */
53 public final class DeckReader {
54
55 /***
56 * Create a new instance of this class.
57 */
58 private DeckReader() {
59
60 }
61
62 private static final int DELIM_COMMA = 1;
63
64 private static final int DELIM_SPACE2 = 2;
65
66 /***
67 * Return the deck component corresponding to the given stream.
68 *
69 * @param deckStream
70 * the deck stream.
71 * @return the deck component corresponding to the given stream.
72 */
73 public static Deck getDeck(MInputStream deckStream) {
74 final Deck deck = new Deck("unknown");
75 String line = null;
76
77
78 line = deckStream.readLine();
79 while (line != null && !"%EOF%".equals(line)) {
80
81 if (line.length() != 0 && !line.startsWith("#")) {
82
83
84 int index = line.indexOf(" ");
85 int format = 0;
86 if (index == -1) {
87
88 index = line.indexOf(";");
89 format = DELIM_COMMA;
90 } else {
91 format = DELIM_SPACE2;
92 }
93 if (index != -1) {
94 String croppedLine = (line + " ").substring(index + 1).trim();
95 String cardName;
96 int nextIndex = croppedLine.indexOf(";");
97 int nb = 0;
98 switch (format) {
99 case DELIM_COMMA:
100 cardName = line.substring(0, index).trim();
101 if (nextIndex == -1) {
102 nb = Integer.parseInt(croppedLine);
103 } else {
104 nb = Integer.parseInt(croppedLine.substring(0, nextIndex).trim());
105 }
106 break;
107 case DELIM_SPACE2:
108 nb = Integer.parseInt(line.substring(0, index).trim());
109 if (nextIndex == -1) {
110 cardName = croppedLine;
111 } else {
112 cardName = croppedLine.substring(0, nextIndex);
113 }
114 break;
115 default:
116 throw new InternalError("Unknown delimiter : '" + format + "'");
117 }
118 try {
119 Map<String, String> properties = null;
120 if (nextIndex != -1) {
121
122 properties = new HashMap<String, String>(5);
123 String[] propertiesArray = croppedLine.substring(nextIndex + 1)
124 .trim().split(";");
125 for (String property : propertiesArray) {
126 property = property.trim();
127 if (propertiesArray.length > 0) {
128 int indexOfEqual = property.indexOf("=");
129 if (indexOfEqual != -1) {
130 properties.put(property.substring(0, indexOfEqual),
131 property.substring(indexOfEqual + 1));
132 } else {
133 JOptionPane.showMessageDialog(MagicUIComponents.magicForm,
134 LanguageManager.getString("malformeddeck", line
135 .substring(0, index)), LanguageManager
136 .getString("error"), JOptionPane.ERROR_MESSAGE);
137 }
138 }
139 }
140 }
141 deck.addCard(cardName, nb, properties);
142 } catch (NumberFormatException e) {
143 JOptionPane.showMessageDialog(MagicUIComponents.magicForm,
144 LanguageManager.getString("malformeddeck", line.substring(0,
145 index)), LanguageManager.getString("error"),
146 JOptionPane.ERROR_MESSAGE);
147 }
148 }
149 }
150 line = deckStream.readLine();
151 }
152 return deck;
153 }
154
155 /***
156 * Return the deck component corresponding to the given file.
157 *
158 * @param parentComponent
159 * determines the <code>Frame</code> in which the dialog is
160 * displayed; if <code>null</code>, or if the
161 * <code>parentComponent</code> has no <code>Frame</code>, a
162 * default <code>Frame</code> is used
163 * @param deckFile
164 * the deck file.
165 * @return the deck component corresponding to the given file.
166 * @throws FileNotFoundException
167 */
168 public static Deck getDeck(Component parentComponent, String deckFile)
169 throws FileNotFoundException {
170 if (deckFile.length() == 0) {
171 if (parentComponent != null) {
172 JOptionPane.showMessageDialog(parentComponent, LanguageManager
173 .getString("wiz_network.deck.missed"), LanguageManager
174 .getString("error"), JOptionPane.WARNING_MESSAGE);
175 }
176 return null;
177 }
178 final String deckShortFile = MToolKit.getShortDeckFile(deckFile);
179 final InputStream deckStream = MToolKit.getResourceAsStream(deckShortFile);
180 if (deckStream == null) {
181 JOptionPane.showMessageDialog(parentComponent, LanguageManager
182 .getString("wiz_network.deck.notfound"), LanguageManager
183 .getString("error"), JOptionPane.WARNING_MESSAGE);
184 throw new RuntimeException("Could not open deck file '" + deckShortFile
185 + "'");
186 }
187 return getDeck(new MInputStream(new FileInputStream(deckShortFile), null));
188 }
189
190 /***
191 * Fill player's zone with the cards found in InputFile
192 *
193 * @param deck
194 * the deck to add.
195 * @param dbFile
196 * opened file read containing the available cards
197 * @param zone
198 * the destination zone.
199 * @param owner
200 * the player owning the created cards.
201 * @throws IOException
202 * If some other I/O error occurs
203 */
204 public static void fillZone(Deck deck, FileInputStream dbFile, MZone zone,
205 Player owner) throws IOException {
206
207 LoaderConsole
208 .beginTask(
209 LanguageManager.getString("wiz_network.validatingdeck"),
210 ((ConnectionManager.client == null && !owner.isYou()) || (ConnectionManager.client != null && owner
211 .isYou())) ? 35 : 65);
212 owner.setDeck(deck);
213
214
215 LoaderConsole
216 .beginTask(
217 LanguageManager.getString("wiz_network.loadingcards"),
218 ((ConnectionManager.client == null && !owner.isYou()) || (ConnectionManager.client != null && owner
219 .isYou())) ? 45 : 75);
220 MCard lastLoadedCard = null;
221 for (MCardCompare cardCompare : deck.getCards()) {
222 final String realCardName = cardCompare.getName();
223 final int nbCards = cardCompare.getAmount();
224 Log.debug(cardCompare);
225 MCard cardRef = null;
226 if (lastLoadedCard != null
227 && realCardName.equals(lastLoadedCard.getName())) {
228 DatabaseCard database = DatabaseFactory.getDatabase(null,
229 lastLoadedCard.getCardModel(), cardCompare.getConstraints());
230 cardRef = new MCard(lastLoadedCard, database);
231 } else {
232 dbFile.getChannel().position(cardCompare.getMdbOffset());
233 cardRef = new MCard(realCardName, dbFile, owner, owner, cardCompare
234 .getConstraints());
235 lastLoadedCard = cardRef;
236 }
237 cardRef.moveCard(zone.getZoneId(), owner, false, IdPositions.ON_THE_TOP);
238
239
240 for (int a = nbCards; a-- > 1;) {
241 new MCard(cardRef, cardRef.getDatabase()).moveCard(zone.getZoneId(),
242 owner, false, IdPositions.ON_THE_TOP);
243 }
244 }
245
246 }
247
248 /***
249 * Read available cards from file and add them to the specified
250 * <code>cardNames</code>
251 *
252 * @param cardNames
253 * to this list method add card names
254 */
255 public static void readAvailableCards(MListModel<MCardCompare> cardNames) {
256 final FileInputStream dbStream = MdbLoader.resetMdb();
257 try {
258 cardNames.clear();
259 while (dbStream.available() > 3) {
260
261 String cardName = MToolKit.readString(dbStream);
262
263
264 long offset = MToolKit.readInt24(dbStream);
265
266 cardNames.add(new MCardCompare(cardName, offset));
267 }
268 } catch (IOException ex2) {
269
270 }
271 }
272
273 /***
274 * Validate a deck read from the given stream.
275 *
276 * @param parentComponent
277 * determines the <code>Frame</code> in which the dialog is
278 * displayed; if <code>null</code>, or if the
279 * <code>parentComponent</code> has no <code>Frame</code>, a
280 * default <code>Frame</code> is used
281 * @param deck
282 * @param deckConstraint
283 * the deck constraint name.
284 * @return <code>true</code> if the read deck is valid.
285 * @throws IOException
286 * If some other I/O error occurs
287 */
288 public static boolean validateDeck(Component parentComponent, Deck deck,
289 String deckConstraint) throws IOException {
290 if (deckConstraint == null) {
291 return validateDeck(parentComponent, deck, (DeckConstraint) null);
292 }
293 return validateDeck(parentComponent, deck, DeckConstraints
294 .getDeckConstraint(deckConstraint));
295 }
296
297 /***
298 * Validate a deck read from the given stream.
299 *
300 * @param parentComponent
301 * determines the <code>Frame</code> in which the dialog is
302 * displayed; if <code>null</code>, or if the
303 * <code>parentComponent</code> has no <code>Frame</code>, a
304 * default <code>Frame</code> is used
305 * @param deck
306 * @param deckConstraint
307 * the deck constraint name.
308 * @return <code>true</code> if the read deck is valid.
309 * @throws IOException
310 * If some other I/O error occurs
311 */
312 public static boolean validateDeck(Component parentComponent, Deck deck,
313 DeckConstraint deckConstraint) throws IOException {
314 final List<String> errors = deck.validate(deckConstraint);
315 if (!errors.isEmpty()) {
316 NetworkActor.cancelling = true;
317 JOptionPane.showMessageDialog(parentComponent, LanguageManager.getString(
318 "wiz_network.deck.constraint.error", deckConstraint
319 .getConstraintLocalName())
320 + " :\n" + errors.toString(), LanguageManager
321 .getString("wiz_network.deck.constraint.error.title"),
322 JOptionPane.ERROR_MESSAGE);
323 return false;
324 }
325 return true;
326 }
327 }