1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package net.sf.magicproject.deckbuilder;
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27
28 import javax.swing.JOptionPane;
29
30 import net.sf.magicproject.action.ActionFactory;
31 import net.sf.magicproject.clickable.ability.AbilityFactory;
32 import net.sf.magicproject.clickable.targetable.card.CardFactory;
33 import net.sf.magicproject.clickable.targetable.card.Damage;
34 import net.sf.magicproject.database.DatabaseFactory;
35 import net.sf.magicproject.modifier.ObjectFactory;
36 import net.sf.magicproject.stack.EventManager;
37 import net.sf.magicproject.stack.MPhase;
38 import net.sf.magicproject.stack.StackManager;
39 import net.sf.magicproject.test.TestFactory;
40 import net.sf.magicproject.token.IdCommonToken;
41 import net.sf.magicproject.tools.MToolKit;
42 import net.sf.magicproject.ui.MagicUIComponents;
43 import net.sf.magicproject.ui.i18n.LanguageManager;
44 import net.sf.magicproject.xml.XmlConfiguration;
45 import net.sf.magicproject.zone.Play;
46 import net.sf.magicproject.zone.ZoneManager;
47
48 import org.apache.commons.io.IOUtils;
49
50 /***
51 * Set of tools to manipulate the MDB format : load headers, finding cards,...
52 *
53 * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
54 * @since 0.54
55 */
56 public final class MdbLoader {
57
58 /***
59 * The first available card's name offset.
60 */
61 private static int firstCardsNamesOffset;
62
63 /***
64 * The first available card's bytes offset.
65 */
66 private static long firstCardsBytesOffset;
67
68 /***
69 * Create a new instance of this class.
70 */
71 private MdbLoader() {
72 super();
73 }
74
75 /***
76 * Load author, tbs name,... Load the rules of this mdb and set them to the MP
77 * environment, set the current offset to the beginning of card section. <br>
78 *
79 * @param dbFile
80 * the mdb file containing rules.
81 * @param firstPlayer
82 * the index of first player.
83 * @return the stream as is, the current offset correponds to the beginning of
84 * cards section.
85 * @throws IOException
86 * If some other I/O error occurs
87 */
88 public static FileInputStream loadMDB(String dbFile, int firstPlayer)
89 throws IOException {
90 FileInputStream dbStream = loadHeader(dbFile);
91
92
93 StackManager.getInstance().init(dbStream, firstPlayer);
94
95
96 EventManager.init(dbStream, dbFile);
97
98
99 MagicUIComponents.databasePanel.init(dbStream);
100
101
102 Play.initSectorConfigurations(dbStream);
103
104
105 resetMdb();
106
107
108
109
110
111 return dbStream;
112 }
113
114 /***
115 * Reset the given MDB stream to the first offset of card references.
116 *
117 * @return the stream.
118 */
119 public static FileInputStream resetMdb() {
120 try {
121 if (lastMdbStream == null) {
122 openMdb(MToolKit.mdbFile, false);
123 }
124 lastMdbStream.getChannel().position(firstCardsNamesOffset);
125 } catch (IOException io) {
126 throw new RuntimeException(io);
127 }
128 return lastMdbStream;
129 }
130
131 /***
132 * Check the given MDB file and update it if needed. Then open it and return
133 * the created stream.
134 *
135 * @param dbStream
136 * the mdb file containing rules.
137 * @param forceRecheck
138 * if true, all files are checked even if it has already been done.
139 * @return return the opened stream as is when file is opened.
140 * @throws IOException
141 * If some other I/O error occurs
142 */
143 public static FileInputStream openMdb(String dbStream, boolean forceRecheck)
144 throws IOException {
145
146 if (lastMdbStream != null && !forceRecheck) {
147 try {
148 lastMdbStream.getChannel().position(0);
149 return lastMdbStream;
150 } catch (IOException io) {
151
152 }
153 }
154
155
156 if (!forceRecheck) {
157 IOUtils.closeQuietly(lastMdbStream);
158 }
159
160
161 final File file = MToolKit.getFile(dbStream);
162 if (!instanceIsChecked || forceRecheck) {
163 final long lastModifiedMdb = file == null ? 0 : file.lastModified();
164 XmlConfiguration.main("-update", MToolKit.tbsName, String
165 .valueOf(lastModifiedMdb));
166 if (XmlConfiguration.error == 0)
167 instanceIsChecked = true;
168 }
169 if (file == null) {
170 lastMdbStream = new FileInputStream(MToolKit.getFile(dbStream));
171 } else {
172 lastMdbStream = new FileInputStream(file);
173 }
174 return lastMdbStream;
175 }
176
177 /***
178 * Load author, tbs name,... Load the rules of this mdb and set them to the MP
179 * environment, set the current offset to the begin of card section and return
180 * it's position Load settings associated to this mdb. <br>
181 *
182 * @param dbFile
183 * the mdb file containing rules.
184 * @return return the opened stream as is, the current offset correponds to
185 * the last byte read of the disclaimer/licence section.
186 * @throws IOException
187 * If some other I/O error occurs
188 */
189 public static FileInputStream loadHeader(String dbFile) throws IOException {
190 if (dbFile.equals(lastMdbFile)) {
191 lastMdbStream.getChannel().position(endOfHeaderOffset);
192 return lastMdbStream;
193 }
194 closeMdb();
195 final FileInputStream dbStream = openMdb(dbFile, false);
196 tbsFullName = MToolKit.readString(dbStream);
197 version = MToolKit.readString(dbStream);
198 author = MToolKit.readString(dbStream);
199 moreInfo = MToolKit.readString(dbStream);
200
201
202 DatabaseFactory.init(dbStream);
203
204 artURL = MToolKit.readString(dbStream);
205 backPicture = MToolKit.readString(dbStream);
206 damagePicture = MToolKit.readString(dbStream);
207 disclaimer = MToolKit.readText(dbStream);
208
209
210 coloredManaSmlURL = MToolKit.readString(dbStream);
211 coloredManaBigURL = MToolKit.readString(dbStream);
212 coloredBigManas = new String[IdCommonToken.COLOR_NAMES.length];
213 coloredSmlManas = new String[IdCommonToken.COLOR_NAMES.length];
214 coloredSmlManasHtml = new String[coloredBigManas.length];
215 for (int i = IdCommonToken.COLOR_NAMES.length; i-- > 1;) {
216 int index = dbStream.read();
217 coloredSmlManas[index] = MToolKit.readString(dbStream);
218 coloredBigManas[index] = MToolKit.readString(dbStream);
219 coloredSmlManasHtml[index] = "<img src='file:///"
220 + MToolKit.getTbsHtmlPicture("mana/colored/small/"
221 + coloredSmlManas[index]) + "'> ";
222 }
223
224
225 colorlessURL = MToolKit.readString(dbStream);
226 colorlessBigURL = MToolKit.readString(dbStream);
227 unknownSmlMana = MToolKit.readString(dbStream);
228 unknownSmlManaHtml = "<img src='file:///"
229 + MToolKit.getTbsHtmlPicture("mana/colorless/small/" + unknownSmlMana)
230 + "'> ";
231 colorlessSmlManas = new String[dbStream.read()];
232 colorlessSmlManasHtml = new String[colorlessSmlManas.length];
233 for (int i = colorlessSmlManas.length; i-- > 0;) {
234 int index = dbStream.read();
235 colorlessSmlManas[index] = MToolKit.readString(dbStream);
236 colorlessSmlManasHtml[index] = "<img src='file:///"
237 + MToolKit.getTbsHtmlPicture("mana/colorless/small/"
238 + colorlessSmlManas[index]) + "'> ";
239 }
240
241
242 firstCardsBytesOffset = MToolKit.readInt24(dbStream);
243
244
245 DeckConstraints.init(dbStream);
246
247
248 ZoneManager.initTbs(dbStream);
249
250
251 TestFactory.init(dbStream);
252
253
254 ActionFactory.init(dbStream);
255
256
257 ObjectFactory.init(dbStream);
258
259
260 AbilityFactory.init(dbStream);
261
262
263 Damage.init(dbStream);
264
265
266 CardFactory.init(dbStream);
267
268
269 endOfHeaderOffset = dbStream.getChannel().position();
270 dbStream.getChannel().position(firstCardsBytesOffset);
271 firstCardsNamesOffset = MToolKit.readInt24(dbStream);
272 dbStream.getChannel().position(endOfHeaderOffset);
273
274 lastMdbFile = dbFile;
275 return dbStream;
276 }
277
278 /***
279 * Save the settings corresponding to the current TBS
280 */
281 public static void saveTBSSettings() {
282 if (MToolKit.mdbFile != null) {
283 saveTBSSettings(MToolKit.mdbFile.replace(".mdb", ".pref"));
284 }
285 }
286
287 /***
288 * Save the settings corresponding to the current TBS
289 *
290 * @param settingFile
291 * the setting file where settings would be saved
292 */
293 private static void saveTBSSettings(String settingFile) {
294
295 if (EventManager.turnStructure == null) {
296
297 return;
298 }
299 try {
300 FileOutputStream out = new FileOutputStream(MToolKit.getFile(settingFile));
301 for (int i = 0; i < EventManager.turnStructure.length; i++) {
302 MPhase.phases[0][i].saveSettings(out);
303 }
304 for (int i = 0; i < EventManager.turnStructure.length; i++) {
305 MPhase.phases[1][i].saveSettings(out);
306 }
307 IOUtils.closeQuietly(out);
308 } catch (java.io.IOException e) {
309 JOptionPane.showMessageDialog(MagicUIComponents.magicForm,
310 LanguageManager.getString("loadtbssettingspb") + " : "
311 + e.getMessage(), LanguageManager.getString("error"),
312 JOptionPane.ERROR_MESSAGE);
313 System.exit(-1);
314 }
315 }
316
317 /***
318 * Loading the settings corresponding to the current TBS
319 */
320 public static void loadTBSSettings() {
321 loadTBSSettings(MToolKit.mdbFile.substring(0, MToolKit.mdbFile
322 .lastIndexOf('.'))
323 + ".pref");
324 }
325
326 /***
327 * Loading the settings corresponding to the specified TBS
328 *
329 * @param settingFile
330 * the setting file where settings have been saved
331 */
332 private static void loadTBSSettings(String settingFile) {
333
334 if (MToolKit.tbsName == null) {
335
336 return;
337 }
338 try {
339 InputStream in = MToolKit.getResourceAsStream(settingFile);
340 for (int i = 0; i < EventManager.turnStructure.length; i++) {
341 MPhase.phases[0][i].loadSettings(in);
342 }
343 for (int i = 0; i < EventManager.turnStructure.length; i++) {
344 MPhase.phases[1][i].loadSettings(in);
345 }
346 IOUtils.closeQuietly(in);
347 } catch (IOException e) {
348 JOptionPane.showMessageDialog(MagicUIComponents.magicForm,
349 LanguageManager.getString("loadtbssettingspb") + " : "
350 + e.getMessage(), LanguageManager.getString("error"),
351 JOptionPane.ERROR_MESSAGE);
352 System.exit(-1);
353 }
354 }
355
356 /***
357 * The current full name of selected TBS
358 */
359 public static String tbsFullName = null;
360
361 /***
362 * The current TBS disclaimer
363 */
364 public static String disclaimer = null;
365
366 /***
367 * The current TBS more information text
368 */
369 public static String moreInfo = null;
370
371 /***
372 * The current TBS comment
373 */
374 public static String author = null;
375
376 /***
377 * The ciurrent TBS version
378 */
379 public static String version = null;
380
381 /***
382 * Indicates where to find the art from a URL
383 */
384 public static String artURL = null;
385
386 /***
387 * Indicates the picture name of the back picture.
388 */
389 public static String backPicture = null;
390
391 /***
392 * Indicates the picture name of the damage picture.
393 */
394 public static String damagePicture = null;
395
396 /***
397 * This is the defined colorless mana file names without basename. The base
398 * web basename is <code>colorlessURL</code> and the local basename is
399 * <code>tbs/TBS_NAME/images/mana/colorless/</code>
400 *
401 * @see #colorlessSmlManas
402 */
403 public static String[] colorlessSmlManas;
404
405 /***
406 * This the HTML representation of defined small colorless manas.
407 *
408 * @see #colorlessSmlManas
409 */
410 public static String[] colorlessSmlManasHtml;
411
412 /***
413 * This is the filename without basename corresponding to the big colorless
414 * picture. The base web basename is <code>colorlessURL</code> and the local
415 * basename is <code>tbs/TBS_NAME/images/mana/colorless/big/</code>
416 */
417 public static String colorlessBigURL;
418
419 /***
420 * This is the defined small colorled mana file names without basename. The
421 * base web basename is <code>coloredManaSmlURL</code> and the local
422 * basename is <code>tbs/TBS_NAME/images/mana/colored/small/</code>
423 *
424 * @see #coloredManaSmlURL
425 */
426 public static String[] coloredSmlManas;
427
428 /***
429 * This the HTML representation of defined small colorled manas.
430 *
431 * @see #colorlessSmlManas
432 */
433 public static String[] coloredSmlManasHtml;
434
435 /***
436 * This is the defined small colorled mana file names without basename. The
437 * base web basename is <code>coloredManaBigURL</code> and the local
438 * basename is <code>tbs/TBS_NAME/images/mana/colored/big/</code>
439 *
440 * @see #coloredManaBigURL
441 */
442 public static String[] coloredBigManas;
443
444 /***
445 * This is the web basename where colorless mana pictures can be found.
446 */
447 public static String colorlessURL;
448
449 /***
450 * This is the web basename where small colorled mana pictures can be found.
451 */
452 public static String coloredManaSmlURL;
453
454 /***
455 * This is the web basename where big colorled mana pictures can be found.
456 */
457 public static String coloredManaBigURL;
458
459 /***
460 * The picture used for unknown mana cost value.
461 */
462 public static String unknownSmlManaHtml;
463
464 /***
465 * The picture used for unknown mana cost value.
466 */
467 public static String unknownSmlMana;
468
469 /***
470 * The offset position of end of header.
471 */
472 private static long endOfHeaderOffset;
473
474 /***
475 * The last loaded Mdb File. Is <code>null</code> while no Mdb has been
476 * loaded..
477 */
478 private static String lastMdbFile;
479
480 /***
481 * Flag indicating if the XML file have benn checked or not for this instance.
482 */
483 private static boolean instanceIsChecked = false;
484
485 /***
486 * The last opened stream of the current MDB.
487 */
488 public static FileInputStream lastMdbStream;
489
490 /***
491 * Close the current TBS.
492 */
493 public static void closeMdb() {
494 IOUtils.closeQuietly(lastMdbStream);
495 lastMdbStream = null;
496 lastMdbFile = null;
497 }
498
499 }