From 8bd5c4a2c47a286c80e4adf81b3f62263b0504e1 Mon Sep 17 00:00:00 2001 From: jendave Date: Sat, 6 Aug 2011 02:44:55 +0000 Subject: [PATCH] new deck format working now! decks are in the res/decks folder, every deck is a file, booster decks are directories with 8 deck files in them. currently, if you run the new version, the decks folder is created automatically, but old decks are neither migrated nor overwritten. i'll commit an import program soon major changes include -Deck doesn't store the three boolean fields any more, but computes them -DeckIO is now an interface, with OldDeckIO and NewDeckIO as its implementations. OldDeckIO will probably still be used for the deck migration tool. --- .gitattributes | 3 +- res/all-decks2 | Bin 28081 -> 113876 bytes res/main.properties | 1 + src/Deck.java | 18 +- src/QuestData_State.java | 2 +- src/forge/Constant.java | 212 ++++++++------- src/forge/Deck.java | 67 +++-- src/forge/DeckIO.java | 207 ++------------ src/forge/Gui_BoosterDraft.java | 16 +- src/forge/Gui_DeckEditor_Menu.java | 9 +- src/forge/Gui_NewGame.java | 124 +++++---- src/forge/Gui_Quest_DeckEditor_Menu.java | 2 +- src/forge/IO.java | 2 +- src/forge/NewDeckIO.java | 327 +++++++++++++++++++++++ src/forge/NewIO.java | 2 +- src/forge/OldDeckIO.java | 202 ++++++++++++++ src/forge/QuestData.java | 2 +- src/forge/_ObjectInputStream.java | 39 --- src/forge/properties/NewConstants.java | 1 + 19 files changed, 798 insertions(+), 438 deletions(-) create mode 100755 src/forge/NewDeckIO.java create mode 100644 src/forge/OldDeckIO.java delete mode 100644 src/forge/_ObjectInputStream.java diff --git a/.gitattributes b/.gitattributes index 8c1459ee88d..f26a019792f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -161,8 +161,10 @@ src/forge/MyButton.java svneol=native#text/plain src/forge/MyObservable.java svneol=native#text/plain src/forge/MyRandom.java svneol=native#text/plain src/forge/NameChanger.java svneol=native#text/plain +src/forge/NewDeckIO.java svneol=native#text/plain src/forge/NewIO.java svneol=native#text/plain src/forge/NonScrollingJEditorPane.java -text svneol=native#text/plain +src/forge/OldDeckIO.java svneol=native#text/plain src/forge/Phase.java svneol=native#text/plain src/forge/PhaseObserver.java svneol=native#text/plain src/forge/PicturePanel.java svneol=native#text/plain @@ -198,7 +200,6 @@ src/forge/Time.java svneol=native#text/plain src/forge/UndoCommand.java svneol=native#text/plain src/forge/Wait.java svneol=native#text/plain src/forge/WinLose.java svneol=native#text/plain -src/forge/_ObjectInputStream.java svneol=native#text/plain src/forge/error/ErrorViewer.java svneol=native#text/plain src/forge/error/ExceptionHandler.java -text svneol=native#text/plain src/forge/gui/ForgeAction.java svneol=native#text/plain diff --git a/res/all-decks2 b/res/all-decks2 index 44d66798b8b989c27eddc16cad7cba081ec91ca1..1afb80e468c51b2355273a36b9835aa18f89accf 100644 GIT binary patch literal 113876 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 LKKy@(-|PPmH|pt* diff --git a/res/main.properties b/res/main.properties index a788f955cc6..263187a2a15 100644 --- a/res/main.properties +++ b/res/main.properties @@ -5,6 +5,7 @@ tokens--file=AllTokens.txt decks--file=all-decks2 booster-decks--file=booster-decks +decks-dir--file=decks card-pictures--file=card-pictures.txt cards--file=cards.txt diff --git a/src/Deck.java b/src/Deck.java index 417ce7be5c0..3109dd5fdc6 100644 --- a/src/Deck.java +++ b/src/Deck.java @@ -1,4 +1,3 @@ -import java.io.ObjectStreamException; import java.io.Serializable; import java.util.ArrayList; @@ -25,20 +24,13 @@ public class Deck implements Serializable { private boolean isSealed; private boolean isDraft; - private ArrayList main = new ArrayList(); - private ArrayList sideboard = new ArrayList(); + private ArrayList main; + private ArrayList sideboard; //very important, do NOT change this - private String name = ""; + private String name; - private Object readResolve() throws ObjectStreamException { - System.out.println("resolving obsolete Deck"); - forge.Deck d = new forge.Deck(deckType); - d.setName(name); - for(String s:main) - d.addMain(s); - for(String s:sideboard) - d.addSideboard(s); - return d; + public forge.Deck migrate() { + return new forge.Deck(deckType, main, sideboard, name); } } diff --git a/src/QuestData_State.java b/src/QuestData_State.java index 7de2c519a94..0a5be654a4b 100644 --- a/src/QuestData_State.java +++ b/src/QuestData_State.java @@ -28,7 +28,7 @@ public class QuestData_State implements Serializable { @SuppressWarnings("unchecked") private Object readResolve() throws ObjectStreamException { - System.out.println("resolving obsolete QuestData_State"); +// System.out.println("resolving obsolete QuestData_State"); //removing generic types to make cast between Deck and forge.Deck //i'm using Deck in this class because it may be somewhere in the serialization stream //it is irrelevant, because readResolve replaces Deck by forge.Deck, and since generics diff --git a/src/forge/Constant.java b/src/forge/Constant.java index 93eff79ecbf..3987aac6f71 100644 --- a/src/forge/Constant.java +++ b/src/forge/Constant.java @@ -1,118 +1,124 @@ + package forge; + + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + import javax.swing.ImageIcon; -public interface Constant -{ - public static final String ProgramName = "MTG Forge - 10/2009 - http://mtgrares.blogspot.com"; - //used to pass information between the GUI screens - public interface Runtime - { - public static final Deck[] HumanDeck = new Deck[1]; - public static final Deck[] ComputerDeck = new Deck[1]; - public static final String[] GameType = new String[1]; - public static final WinLose WinLose = new WinLose(); - public static final boolean[] smooth = new boolean[1]; +public interface Constant { + public static final String ProgramName = "MTG Forge - 10/2009 - http://mtgrares.blogspot.com"; - public static final int[] width = new int[1]; - public static final int[] height = new int[1]; + //used to pass information between the GUI screens + public interface Runtime { + public static final Deck[] HumanDeck = new Deck[1]; + public static final Deck[] ComputerDeck = new Deck[1]; + public static final String[] GameType = new String[1]; + public static final WinLose WinLose = new WinLose(); + public static final boolean[] smooth = new boolean[1]; + + public static final int[] width = new int[1]; + public static final int[] height = new int[1]; + + } - } - public interface GameType - { - public static final String Constructed = "constructed"; - public static final String Sealed = "sealed"; - public static final String Draft = "draft"; - } - public interface IO - { - //TODO: probably should read this from a file, or set from GUI + public interface GameType { + public static final String Constructed = "constructed"; + public static final String Sealed = "sealed"; + public static final String Draft = "draft"; + public static final List GameTypes = Collections.unmodifiableList(Arrays.asList(Constructed, + Sealed, Draft)); + } + + public interface IO { + //TODO: probably should read this from a file, or set from GUI // public static final String baseDir = "c:\\Tim\\game testing\\"; - - public static final String deckFile = "all-decks2"; - public static final String boosterDeckFile = "booster-decks"; - - public static final String imageBaseDir = "pics"; - public static final String cardFile = "cards.txt"; - - public static final ImageIcon upIcon = new ImageIcon ("up.gif"); - public static final ImageIcon downIcon = new ImageIcon ("down.gif"); - public static final ImageIcon leftIcon = new ImageIcon ("left.gif"); - public static final ImageIcon rightIcon = new ImageIcon("right.gif"); - } - public interface Ability - { - public static final String Triggered = "Triggered"; - public static final String Activated = "Activated"; - } - public interface Phase - { - public static final String Untap = "Untap"; - public static final String Upkeep = "Upkeep"; - public static final String Draw = "Draw"; - public static final String Main1 = "Main1"; - //public static final String Begin_Combat = "Beginning of Combat"; - public static final String Combat_Before_Declare_Attackers_InstantAbility = "Before Attack Phase - Play Instants and Abilities"; - public static final String Combat_Declare_Attackers_InstantAbility = "Declare Attackers - Play Instants and Abilities"; - public static final String Combat_Declare_Attackers = "Declare Attackers"; - public static final String Combat_Declare_Blockers = "Declare Blockers"; - public static final String Combat_Declare_Blockers_InstantAbility = "Declare Blockers - Play Instants and Abilities"; - public static final String Combat_Damage = "Combat Damage"; - public static final String Combat_FirstStrikeDamage = "First Strike Damage"; - //public static final String End_Combat = "End of Combat"; - public static final String Main2 = "Main2"; - public static final String At_End_Of_Turn = "At End of Turn"; - public static final String End_Of_Turn = "End of Turn"; - public static final String Until_End_Of_Turn = "Until End of Turn"; - public static final String Cleanup = "Cleanup"; - } - public interface Zone - { - public static final String Hand = "Hand"; - public static final String Library = "Library"; - public static final String Graveyard = "Graveyard"; - public static final String Play = "Play"; - public static final String Removed_From_Play = "Removed from play"; - //public static final String Stack = "Stack"; - } - public interface Player - { - public static final String Human = "Human"; - public static final String Computer = "Computer"; - } + + public static final String deckFile = "all-decks2"; + public static final String boosterDeckFile = "booster-decks"; + + public static final String imageBaseDir = "pics"; + public static final String cardFile = "cards.txt"; + + public static final ImageIcon upIcon = new ImageIcon("up.gif"); + public static final ImageIcon downIcon = new ImageIcon("down.gif"); + public static final ImageIcon leftIcon = new ImageIcon("left.gif"); + public static final ImageIcon rightIcon = new ImageIcon("right.gif"); + } + + public interface Ability { + public static final String Triggered = "Triggered"; + public static final String Activated = "Activated"; + } + + public interface Phase { + public static final String Untap = "Untap"; + public static final String Upkeep = "Upkeep"; + public static final String Draw = "Draw"; + public static final String Main1 = "Main1"; + //public static final String Begin_Combat = "Beginning of Combat"; + public static final String Combat_Before_Declare_Attackers_InstantAbility = "Before Attack Phase - Play Instants and Abilities"; + public static final String Combat_Declare_Attackers_InstantAbility = "Declare Attackers - Play Instants and Abilities"; + public static final String Combat_Declare_Attackers = "Declare Attackers"; + public static final String Combat_Declare_Blockers = "Declare Blockers"; + public static final String Combat_Declare_Blockers_InstantAbility = "Declare Blockers - Play Instants and Abilities"; + public static final String Combat_Damage = "Combat Damage"; + public static final String Combat_FirstStrikeDamage = "First Strike Damage"; + //public static final String End_Combat = "End of Combat"; + public static final String Main2 = "Main2"; + public static final String At_End_Of_Turn = "At End of Turn"; + public static final String End_Of_Turn = "End of Turn"; + public static final String Until_End_Of_Turn = "Until End of Turn"; + public static final String Cleanup = "Cleanup"; + } + + public interface Zone { + public static final String Hand = "Hand"; + public static final String Library = "Library"; + public static final String Graveyard = "Graveyard"; + public static final String Play = "Play"; + public static final String Removed_From_Play = "Removed from play"; + //public static final String Stack = "Stack"; + } + + public interface Player { + public static final String Human = "Human"; + public static final String Computer = "Computer"; + } + /* public interface CardType { - public static final String Artifact = "Artifact"; - public static final String Creature = "Creature"; - public static final String Enchantment = "Enchantment"; - public static final String Aura = "Aura"; - public static final String Instant = "Instant"; - public static final String Land = "Land"; - public static final String Legendary = "Legendary"; - public static final String Sorcery = "Sorcery"; - public static final String Basic = "Basic"; + public static final String Artifact = "Artifact"; + public static final String Creature = "Creature"; + public static final String Enchantment = "Enchantment"; + public static final String Aura = "Aura"; + public static final String Instant = "Instant"; + public static final String Land = "Land"; + public static final String Legendary = "Legendary"; + public static final String Sorcery = "Sorcery"; + public static final String Basic = "Basic"; } */ - public interface Color - { - public static final String Black = "black"; - public static final String Blue = "blue"; - public static final String Green = "green"; - public static final String Red = "red"; - public static final String White = "white"; - - public static final String Colorless = "colorless"; - //color order "wubrg" - public static final String Colors[] = - {White, Blue, Black, Red, Green, Colorless}; - - public static final String onlyColors[] = {White, Blue, Black, Red, Green}; - - public static final String Snow = "snow"; - public static final String ManaColors[] = - {White, Blue, Black, Red, Green, Colorless, Snow}; - } + public interface Color { + public static final String Black = "black"; + public static final String Blue = "blue"; + public static final String Green = "green"; + public static final String Red = "red"; + public static final String White = "white"; + + public static final String Colorless = "colorless"; + //color order "wubrg" + public static final String Colors[] = {White, Blue, Black, Red, Green, Colorless}; + + public static final String onlyColors[] = {White, Blue, Black, Red, Green}; + + public static final String Snow = "snow"; + public static final String ManaColors[] = {White, Blue, Black, Red, Green, Colorless, Snow}; + } }//Constant /* diff --git a/src/forge/Deck.java b/src/forge/Deck.java index 0e8d58a2184..138f1868f36 100644 --- a/src/forge/Deck.java +++ b/src/forge/Deck.java @@ -1,31 +1,45 @@ + package forge; +import static java.util.Collections.*; - -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; public class Deck implements java.io.Serializable { private static final long serialVersionUID = -2188987217361601903L; //gameType is from Constant.GameType, like Constant.GameType.Regular - private String deckType; + private String name, comment, deckType; - private boolean isRegular; - private boolean isSealed; - private boolean isDraft; - - private ArrayList main = new ArrayList(); - private ArrayList sideboard = new ArrayList(); - - //very important, do NOT change this - private String name = ""; + private List main, sideboard, mainView, sideboardView; //gameType is from Constant.GameType, like Constant.GameType.Regular public Deck(String gameType) { - deckType = gameType; setDeckType(gameType); + name = ""; + main = new ArrayList(); + sideboard = new ArrayList(); + mainView = unmodifiableList(main); + sideboardView = unmodifiableList(sideboard); + } + + public Deck(String deckType, List main, List sideboard, String name) { + this.deckType = deckType; + this.main = main; + this.sideboard = main; + this.name = name; + } + + public List getMain() { + return mainView; + } + + public List getSideboard() { + return sideboardView; } public String getDeckType() { @@ -33,14 +47,14 @@ public class Deck implements java.io.Serializable { } //can only call this method ONCE - private final void setDeckType(String deckType) { - if(isRegular || isSealed || isDraft) throw new RuntimeException( + private void setDeckType(String deckType) { + if(this.deckType != null) throw new IllegalStateException( "Deck : setDeckType() error, deck type has already been set"); - if(deckType.equals(Constant.GameType.Constructed)) isRegular = true; - else if(deckType.equals(Constant.GameType.Sealed)) isSealed = true; - else if(deckType.equals(Constant.GameType.Draft)) isDraft = true; - else throw new RuntimeException("Deck : setDeckType() error, invalid deck type - " + deckType); + if(!Constant.GameType.GameTypes.contains(deckType)) throw new RuntimeException( + "Deck : setDeckType() error, invalid deck type - " + deckType); + + this.deckType = deckType; } public void setName(String s) { @@ -51,6 +65,14 @@ public class Deck implements java.io.Serializable { return name; }//may return null + public void setComment(String comment) { + this.comment = comment; + } + + public String getComment() { + return comment; + } + public void addMain(String cardName) { main.add(cardName); } @@ -84,21 +106,22 @@ public class Deck implements java.io.Serializable { } public boolean isDraft() { - return isDraft; + return deckType.equals(Constant.GameType.Draft); } public boolean isSealed() { - return isSealed; + return deckType.equals(Constant.GameType.Sealed); } public boolean isRegular() { - return isRegular; + return deckType.equals(Constant.GameType.Constructed); } public int hashcode() { return getName().hashCode(); } + @Override public String toString() { return getName(); } diff --git a/src/forge/DeckIO.java b/src/forge/DeckIO.java index 817f743a076..9bcbcc73838 100644 --- a/src/forge/DeckIO.java +++ b/src/forge/DeckIO.java @@ -1,202 +1,45 @@ +/** + * DeckIO.java + * + * Created on 01.11.2009 + */ package forge; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; import java.util.Map; -import forge.error.ErrorViewer; - -//reads and write Deck objects -public class DeckIO { - private final File file; - private ArrayList deckList = new ArrayList(); +/** + * The class DeckIO. + * + * @version V0.0 01.11.2009 + * @author Clemens Koza + */ +public interface DeckIO { - //key is String of the humans deck - //data is Deck[] size of 8 - //humans deck is Deck[0] - private Map boosterMap = new HashMap(); + public boolean isUnique(String deckName); - public static void main(String[] args) { - Deck[] deck = new Deck[8]; - for(int i = 0; i < deck.length; i++) { - deck[i] = new Deck(Constant.GameType.Draft); - deck[i].setName("" + i); - } - - deck[0].addMain("Lantern Kami"); - - //DeckIO io = new DeckIO("booster-decks"); -// io.writeBoosterDeck(deck); -// io.close(); - -// io.deleteBoosterDeck("0"); -// System.out.println(io.getBoosterDecks().keySet().size()); -// io.close(); - } + public boolean isUniqueDraft(String deckName); - public DeckIO(String filename) { - this(new File(filename)); - } + public boolean hasName(String deckName); - public DeckIO(File file) { - this.file = file; - - readFile(); - } + public Deck readDeck(String deckName); - public boolean isUnique(String deckName) { - Deck d; - for(int i = 0; i < deckList.size(); i++) { - d = deckList.get(i); - if(d.getName().equals(deckName)) return false; - } - return true; - } + public void writeDeck(Deck deck); - public boolean isUniqueDraft(String deckName) { - ArrayList key = new ArrayList(boosterMap.keySet()); - - for(int i = 0; i < key.size(); i++) { - if(key.get(i).equals(deckName)) return false; - } - return true; - } + public void deleteDeck(String deckName); - public boolean hasName(String deckName) { - ArrayList string = new ArrayList(); - - for(int i = 0; i < deckList.size(); i++) - string.add(deckList.get(i).toString()); - - Iterator it = boosterMap.keySet().iterator(); - while(it.hasNext()) - string.add(it.next().toString()); - - return string.contains(deckName); - } + public Deck[] readBoosterDeck(String deckName); - public Deck readDeck(String deckName) { - return deckList.get(findDeckIndex(deckName)); - } + public void writeBoosterDeck(Deck[] deck);//writeBoosterDeck() - private int findDeckIndex(String deckName) { - int n = -1; - for(int i = 0; i < deckList.size(); i++) - if((deckList.get(i)).getName().equals(deckName)) n = i; - - if(n == -1) throw new RuntimeException("DeckIO : findDeckIndex() error, deck name not found - " + deckName); - - return n; - } + public void deleteBoosterDeck(String deckName); - public void writeDeck(Deck deck) { - if(deck.getDeckType().equals(Constant.GameType.Draft)) throw new RuntimeException( - "DeckIO : writeDeck() error, deck type is Draft"); - - deckList.add(deck); - } + public Deck[] getDecks(); - public void deleteDeck(String deckName) { - deckList.remove(findDeckIndex(deckName)); - } + public Map getBoosterDecks(); - public Deck[] readBoosterDeck(String deckName) { - if(!boosterMap.containsKey(deckName)) throw new RuntimeException( - "DeckIO : readBoosterDeck() error, deck name not found - " + deckName); - - return boosterMap.get(deckName); - } + public void close(); - public void writeBoosterDeck(Deck[] deck) { - checkBoosterDeck(deck); - - boosterMap.put(deck[0].toString(), deck); - }//writeBoosterDeck() - - public void deleteBoosterDeck(String deckName) { - if(!boosterMap.containsKey(deckName)) throw new RuntimeException( - "DeckIO : deleteBoosterDeck() error, deck name not found - " + deckName); - - boosterMap.remove(deckName); - } - - private void checkBoosterDeck(Deck[] deck) { - if(deck == null || deck.length != 8 || deck[0].getName().equals("") - || (!deck[0].getDeckType().equals(Constant.GameType.Draft))) { - throw new RuntimeException("DeckIO : checkBoosterDeck() error, invalid deck"); - } -// for(int i = 0; i < deck.length; i++) -// if(deck[i].getName().equals("")) -// throw new RuntimeException("DeckIO : checkBoosterDeck() error, deck does not have name - " +deck[i].getName()); - }//checkBoosterDeck() - - - public Deck[] getDecks() { - Deck[] out = new Deck[deckList.size()]; - deckList.toArray(out); - return out; - } - - public Map getBoosterDecks() { - return new HashMap(boosterMap); - } - - public void close() { - writeFile(); - } - - @SuppressWarnings("unchecked") - // ArrayList and Map have unchecked casts - private void readFile() { - try { -//~ - // Shouldn't ever get here, but just in case... - if(file == null) { - return; - } -//~ - if(!file.exists()) return; - - ObjectInputStream in = new _ObjectInputStream(new FileInputStream(file)); - - deckList = (ArrayList) in.readObject(); - boosterMap = (Map) in.readObject(); - - in.close(); - } catch(Exception ex) { - ErrorViewer.showError(ex); - throw new RuntimeException("DeckIO : read() error, " + ex); - } - } - - private void writeFile() { - try { -//~ - if(file == null) { - return; - } -//~ - if(!file.exists()) file.createNewFile(); - - ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file)); - - out.writeObject(deckList); - out.writeObject(boosterMap); - - out.flush(); - out.close(); - } catch(Exception ex) { - ErrorViewer.showError(ex); - throw new RuntimeException("DeckIO : write() error, " + ex.getMessage()); - } - } -}//DeckIO +} diff --git a/src/forge/Gui_BoosterDraft.java b/src/forge/Gui_BoosterDraft.java index 97af615b38c..771dec033da 100644 --- a/src/forge/Gui_BoosterDraft.java +++ b/src/forge/Gui_BoosterDraft.java @@ -1,4 +1,7 @@ + package forge; + + import java.awt.BorderLayout; import java.awt.Color; import java.awt.Frame; @@ -37,7 +40,6 @@ import forge.properties.ForgeProps; import forge.properties.NewConstants; - public class Gui_BoosterDraft extends JFrame implements CardDetail, NewConstants, NewConstants.LANG.Gui_BoosterDraft { private static final long serialVersionUID = -6055633915602448260L; @@ -450,7 +452,7 @@ public class Gui_BoosterDraft extends JFrame implements CardDetail, NewConstants private void refreshGui() { Deck deck = Constant.Runtime.HumanDeck[0]; if(deck == null) //this is just a patch, i know - deck = new Deck(Constant.Runtime.GameType[0]); + deck = new Deck(Constant.Runtime.GameType[0]); allCardModel.clear(); deckModel.clear(); @@ -461,8 +463,7 @@ public class Gui_BoosterDraft extends JFrame implements CardDetail, NewConstants c = AllZone.CardFactory.getCard(deck.getMain(i), Constant.Player.Human); //add rarity to card if this is a sealed card pool - if(!Constant.Runtime.GameType[0].equals(Constant.GameType.Constructed)) - c.setRarity(pack.getRarity(c.getName()));; + if(!Constant.Runtime.GameType[0].equals(Constant.GameType.Constructed)) c.setRarity(pack.getRarity(c.getName()));; deckModel.addCard(c); }//for @@ -510,7 +511,7 @@ public class Gui_BoosterDraft extends JFrame implements CardDetail, NewConstants //pick card int n = allCardTable.getSelectedRow(); if(n == -1) //is valid selection? - return; + return; Card c = allCardModel.rowToCard(n); @@ -582,7 +583,8 @@ public class Gui_BoosterDraft extends JFrame implements CardDetail, NewConstants Deck[] all = { human, computer[0], computer[1], computer[2], computer[3], computer[4], computer[5], computer[6]}; - DeckIO deckIO = new DeckIO(ForgeProps.getFile(BOOSTER_DECKS)); +// DeckIO deckIO = new OldDeckIO(ForgeProps.getFile(BOOSTER_DECKS)); + DeckIO deckIO = new NewDeckIO(ForgeProps.getFile(NEW_DECKS)); deckIO.writeBoosterDeck(all); //write file @@ -592,4 +594,4 @@ public class Gui_BoosterDraft extends JFrame implements CardDetail, NewConstants dispose(); new Gui_NewGame(); }/*saveDraft()*/ -} \ No newline at end of file +} diff --git a/src/forge/Gui_DeckEditor_Menu.java b/src/forge/Gui_DeckEditor_Menu.java index e4b530176ed..31f14f137a7 100644 --- a/src/forge/Gui_DeckEditor_Menu.java +++ b/src/forge/Gui_DeckEditor_Menu.java @@ -51,8 +51,11 @@ public class Gui_DeckEditor_Menu extends JMenuBar implements NewConstants { private final boolean debugPrint = false; - private final DeckIO deckIO = new DeckIO(ForgeProps.getFile(DECKS)); - private final DeckIO boosterDeckIO = new DeckIO(ForgeProps.getFile(BOOSTER_DECKS)); +// private final DeckIO deckIO = new OldDeckIO(ForgeProps.getFile(DECKS)); +// private final DeckIO boosterDeckIO = new OldDeckIO(ForgeProps.getFile(BOOSTER_DECKS)); + private final DeckIO deckIO = new NewDeckIO(ForgeProps.getFile(NEW_DECKS)); + //with the new IO, there's no reason to use different instances + private final DeckIO boosterDeckIO = deckIO; private boolean isDeckSaved; private String currentDeckName; @@ -329,7 +332,7 @@ public class Gui_DeckEditor_Menu extends JMenuBar implements NewConstants { Object check = null; try { - ObjectInputStream in = new _ObjectInputStream(new FileInputStream(file)); + ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); check = in.readObject(); in.close(); diff --git a/src/forge/Gui_NewGame.java b/src/forge/Gui_NewGame.java index e1abee290af..dc6765dbe90 100644 --- a/src/forge/Gui_NewGame.java +++ b/src/forge/Gui_NewGame.java @@ -1,5 +1,7 @@ + package forge; + import java.awt.Color; import java.awt.Component; import java.awt.Dimension; @@ -47,32 +49,35 @@ import forge.properties.NewConstants.LANG.Gui_NewGame.MENU_BAR.OPTIONS; public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LANG.Gui_NewGame { private static final long serialVersionUID = -2437047615019135648L; - private final DeckIO deckIO = new DeckIO(ForgeProps.getFile(DECKS)); - private final DeckIO boosterDeckIO = new DeckIO(ForgeProps.getFile(BOOSTER_DECKS)); +// private final DeckIO deckIO = new OldDeckIO(ForgeProps.getFile(DECKS)); +// private final DeckIO boosterDeckIO = new OldDeckIO(ForgeProps.getFile(BOOSTER_DECKS)); + private final DeckIO deckIO = new NewDeckIO(ForgeProps.getFile(NEW_DECKS)); + //with the new IO, there's no reason to use different instances + private final DeckIO boosterDeckIO = deckIO; private ArrayList allDecks; private static Gui_DeckEditor editor; - private JLabel titleLabel = new JLabel(); - private JLabel jLabel2 = new JLabel(); - private JLabel jLabel3 = new JLabel(); - private JComboBox humanComboBox = new JComboBox(); - private JComboBox computerComboBox = new JComboBox(); - private JButton deckEditorButton = new JButton(); - private JButton startButton = new JButton(); - private ButtonGroup buttonGroup1 = new ButtonGroup(); - private JRadioButton sealedRadioButton = new JRadioButton(); - private JRadioButton singleRadioButton = new JRadioButton(); - private JPanel jPanel2 = new JPanel(); - private Border border1; - private TitledBorder titledBorder1; - private JRadioButton draftRadioButton = new JRadioButton(); - private JPanel jPanel1 = new JPanel(); - private Border border2; + private JLabel titleLabel = new JLabel(); + private JLabel jLabel2 = new JLabel(); + private JLabel jLabel3 = new JLabel(); + private JComboBox humanComboBox = new JComboBox(); + private JComboBox computerComboBox = new JComboBox(); + private JButton deckEditorButton = new JButton(); + private JButton startButton = new JButton(); + private ButtonGroup buttonGroup1 = new ButtonGroup(); + private JRadioButton sealedRadioButton = new JRadioButton(); + private JRadioButton singleRadioButton = new JRadioButton(); + private JPanel jPanel2 = new JPanel(); + private Border border1; + private TitledBorder titledBorder1; + private JRadioButton draftRadioButton = new JRadioButton(); + private JPanel jPanel1 = new JPanel(); + private Border border2; @SuppressWarnings("unused") // titledBorder2 - private TitledBorder titledBorder2; - private static JCheckBox newGuiCheckBox = new JCheckBox("", true); - private static JCheckBox smoothLandCheckBox = new JCheckBox("", true); + private TitledBorder titledBorder2; + private static JCheckBox newGuiCheckBox = new JCheckBox("", true); + private static JCheckBox smoothLandCheckBox = new JCheckBox("", true); // GenerateConstructedDeck.get2Colors() and GenerateSealedDeck.get2Colors() // use these two variables @@ -81,7 +86,7 @@ public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LA public static JCheckBoxMenuItem removeArtifacts = new JCheckBoxMenuItem( ForgeProps.getLocalized(MENU_BAR.OPTIONS.GENERATE.REMOVE_ARTIFACTS)); - private JButton questButton = new JButton(); + private JButton questButton = new JButton(); private Action LOOK_AND_FEEL_ACTION = new LookAndFeelAction(this); private Action DOWNLOAD_ACTION = new DownloadAction(); @@ -90,7 +95,7 @@ public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LA public static void main(String[] args) { ExceptionHandler.registerErrorHandling(); - try { + try { Object[] o = UIManager.getInstalledLookAndFeels(); if(o.length > 3) { final Color background = new Color(204, 204, 204); @@ -102,7 +107,7 @@ public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LA "Dialog.background", "OptionPane.background", "ScrollBar.background"}; for(int i = 0; i < properties.length; i++) { //UIManager.put(properties, background); - UIManager.put(properties[i], background); + UIManager.put(properties[i], background); } } } catch(Exception ex) { @@ -402,19 +407,15 @@ public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LA if(humanGenerate) { if(constructed) Constant.Runtime.HumanDeck[0] = generateConstructedDeck(); else if(sealed) Constant.Runtime.HumanDeck[0] = generateSealedDeck(); - } - else if (humanGenerateMulti3) { - if(constructed) Constant.Runtime.HumanDeck[0] = generateConstructed3ColorDeck(); - } - else if (humanGenerateMulti5) { - if(constructed) Constant.Runtime.HumanDeck[0] = generateConstructed5ColorDeck(); - } - else if(humanRandom) { + } else if(humanGenerateMulti3) { + if(constructed) Constant.Runtime.HumanDeck[0] = generateConstructed3ColorDeck(); + } else if(humanGenerateMulti5) { + if(constructed) Constant.Runtime.HumanDeck[0] = generateConstructed5ColorDeck(); + } else if(humanRandom) { Constant.Runtime.HumanDeck[0] = getRandomDeck(getDecks(format)); JOptionPane.showMessageDialog(null, String.format("You are using deck: %s", Constant.Runtime.HumanDeck[0].getName()), "Deck Name", JOptionPane.INFORMATION_MESSAGE); - } - else { + } else { Constant.Runtime.HumanDeck[0] = deckIO.readDeck(human); } @@ -427,14 +428,11 @@ public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LA if(computerGenerate) { if(constructed) Constant.Runtime.ComputerDeck[0] = generateConstructedDeck(); else if(sealed) Constant.Runtime.ComputerDeck[0] = generateSealedDeck(); - } - else if (computerGenerateMulti3) { - if(constructed) Constant.Runtime.ComputerDeck[0] = generateConstructed3ColorDeck(); - } - else if (computerGenerateMulti5) { - if(constructed) Constant.Runtime.ComputerDeck[0] = generateConstructed5ColorDeck(); - } - else if(computerRandom) { + } else if(computerGenerateMulti3) { + if(constructed) Constant.Runtime.ComputerDeck[0] = generateConstructed3ColorDeck(); + } else if(computerGenerateMulti5) { + if(constructed) Constant.Runtime.ComputerDeck[0] = generateConstructed5ColorDeck(); + } else if(computerRandom) { Constant.Runtime.ComputerDeck[0] = getRandomDeck(getDecks(format)); JOptionPane.showMessageDialog(null, String.format("The computer is using deck: %s", Constant.Runtime.ComputerDeck[0].getName()), "Deck Name", JOptionPane.INFORMATION_MESSAGE); @@ -479,7 +477,7 @@ public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LA } private Deck generateConstructed3ColorDeck() { - GenerateConstructedMultiColorDeck gen = new GenerateConstructedMultiColorDeck(); + GenerateConstructedMultiColorDeck gen = new GenerateConstructedMultiColorDeck(); CardList name = gen.generate3ColorDeck(); Deck deck = new Deck(Constant.GameType.Constructed); @@ -489,7 +487,7 @@ public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LA } private Deck generateConstructed5ColorDeck() { - GenerateConstructedMultiColorDeck gen = new GenerateConstructedMultiColorDeck(); + GenerateConstructedMultiColorDeck gen = new GenerateConstructedMultiColorDeck(); CardList name = gen.generate5ColorDeck(); Deck deck = new Deck(Constant.GameType.Constructed); @@ -580,9 +578,9 @@ public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LA }/* draftRadioButton_actionPerformed() */ public static class LookAndFeelAction extends AbstractAction { - - private static final long serialVersionUID = -4447498333866711215L; - private Component c; + + private static final long serialVersionUID = -4447498333866711215L; + private Component c; public LookAndFeelAction(Component c) { super(ForgeProps.getLocalized(MENU_BAR.MENU.LF)); @@ -607,29 +605,29 @@ public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LA } public static class DownloadAction extends AbstractAction { - - private static final long serialVersionUID = 6564425021778307101L; - - public DownloadAction() { + + private static final long serialVersionUID = 6564425021778307101L; + + public DownloadAction() { super(ForgeProps.getLocalized(MENU_BAR.MENU.DOWNLOAD)); } - + public void actionPerformed(ActionEvent e) { Gui_DownloadPictures.startDownload(null); } } public static class CardSizesAction extends AbstractAction { - - private static final long serialVersionUID = -2900235618450319571L; - private String[] keys = {"Tiny", "Small", "Medium", "Large"}; - private int[] widths = {42, 63, 70, 93}; - private int[] heights = {59, 88, 98, 130}; + + private static final long serialVersionUID = -2900235618450319571L; + private String[] keys = {"Tiny", "Small", "Medium", "Large"}; + private int[] widths = {42, 63, 70, 93}; + private int[] heights = {59, 88, 98, 130}; public CardSizesAction() { super(ForgeProps.getLocalized(MENU_BAR.MENU.CARD_SIZES)); } - + public void actionPerformed(ActionEvent e) { ListChooser ch = new ListChooser("Choose one", "Choose a new card size", 0, 1, keys); if(ch.show()) try { @@ -644,10 +642,10 @@ public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LA } public static class AboutAction extends AbstractAction { - - private static final long serialVersionUID = 5492173304463396871L; - - public AboutAction() { + + private static final long serialVersionUID = 5492173304463396871L; + + public AboutAction() { super(ForgeProps.getLocalized(MENU_BAR.MENU.ABOUT)); } @@ -668,4 +666,4 @@ public class Gui_NewGame extends JFrame implements NewConstants, NewConstants.LA JOptionPane.showMessageDialog(null, area, "About", JOptionPane.INFORMATION_MESSAGE); } } -} \ No newline at end of file +} diff --git a/src/forge/Gui_Quest_DeckEditor_Menu.java b/src/forge/Gui_Quest_DeckEditor_Menu.java index 42947644b67..af8528b9777 100644 --- a/src/forge/Gui_Quest_DeckEditor_Menu.java +++ b/src/forge/Gui_Quest_DeckEditor_Menu.java @@ -264,7 +264,7 @@ public class Gui_Quest_DeckEditor_Menu extends JMenuBar { Object check = null; try { - ObjectInputStream in = new _ObjectInputStream(new FileInputStream(file)); + ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); check = in.readObject(); in.close(); diff --git a/src/forge/IO.java b/src/forge/IO.java index cc808b821f6..a3e762e9b43 100644 --- a/src/forge/IO.java +++ b/src/forge/IO.java @@ -39,7 +39,7 @@ public class IO { // Map has unchecked cast private void readMap() { try { - ObjectInputStream in = new _ObjectInputStream(new FileInputStream(file)); + ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); map = (Map) in.readObject(); in.close(); } catch(Exception ex) { diff --git a/src/forge/NewDeckIO.java b/src/forge/NewDeckIO.java new file mode 100755 index 00000000000..89879716bdf --- /dev/null +++ b/src/forge/NewDeckIO.java @@ -0,0 +1,327 @@ + +package forge; + + +import static java.lang.Integer.*; +import static java.lang.String.*; +import static java.util.Arrays.*; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import forge.error.ErrorViewer; + + +//reads and write Deck objects +public class NewDeckIO implements DeckIO { + private static FilenameFilter dck = new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".dck"); + } + }; + private static FilenameFilter bdk = new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".bdk"); + } + }; + + private File dir; + List deckList; + Map boosterMap; + + public NewDeckIO(String fileName) { + this(new File(fileName)); + } + + public NewDeckIO(File dir) { + try { + this.dir = dir; + + if(dir.isFile()) { + throw new IOException("Not a directory"); + } else { + dir.mkdirs(); + if(!dir.isDirectory()) throw new IOException("Directory can't be created"); + deckList = new ArrayList(); + boosterMap = new HashMap(); + readFile(); + } + } catch(IOException ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("DeckIO : write() error, " + ex.getMessage()); + } + } + + public boolean isUnique(String deckName) { + Deck d; + for(int i = 0; i < deckList.size(); i++) { + d = deckList.get(i); + if(d.getName().equals(deckName)) return false; + } + return true; + } + + public boolean isUniqueDraft(String deckName) { + ArrayList key = new ArrayList(boosterMap.keySet()); + + for(int i = 0; i < key.size(); i++) { + if(key.get(i).equals(deckName)) return false; + } + return true; + } + + public boolean hasName(String deckName) { + ArrayList string = new ArrayList(); + + for(int i = 0; i < deckList.size(); i++) + string.add(deckList.get(i).toString()); + + Iterator it = boosterMap.keySet().iterator(); + while(it.hasNext()) + string.add(it.next().toString()); + + return string.contains(deckName); + } + + public Deck readDeck(String deckName) { + return deckList.get(findDeckIndex(deckName)); + } + + private int findDeckIndex(String deckName) { + int n = -1; + for(int i = 0; i < deckList.size(); i++) + if((deckList.get(i)).getName().equals(deckName)) n = i; + + if(n == -1) throw new RuntimeException("DeckIO : findDeckIndex() error, deck name not found - " + deckName); + + return n; + } + + public void writeDeck(Deck deck) { + if(deck.getDeckType().equals(Constant.GameType.Draft)) throw new RuntimeException( + "DeckIO : writeDeck() error, deck type is Draft"); + + deckList.add(deck); + } + + public void deleteDeck(String deckName) { + deckList.remove(findDeckIndex(deckName)); + } + + public Deck[] readBoosterDeck(String deckName) { + if(!boosterMap.containsKey(deckName)) throw new RuntimeException( + "DeckIO : readBoosterDeck() error, deck name not found - " + deckName); + + return boosterMap.get(deckName); + } + + public void writeBoosterDeck(Deck[] deck) { + checkBoosterDeck(deck); + + boosterMap.put(deck[0].toString(), deck); + }//writeBoosterDeck() + + public void deleteBoosterDeck(String deckName) { + if(!boosterMap.containsKey(deckName)) throw new RuntimeException( + "DeckIO : deleteBoosterDeck() error, deck name not found - " + deckName); + + boosterMap.remove(deckName); + } + + private void checkBoosterDeck(Deck[] deck) { + if(deck == null || deck.length != 8 || deck[0].getName().equals("") + || (!deck[0].getDeckType().equals(Constant.GameType.Draft))) { + throw new RuntimeException("DeckIO : checkBoosterDeck() error, invalid deck"); + } +// for(int i = 0; i < deck.length; i++) +// if(deck[i].getName().equals("")) +// throw new RuntimeException("DeckIO : checkBoosterDeck() error, deck does not have name - " +deck[i].getName()); + }//checkBoosterDeck() + + + public Deck[] getDecks() { + Deck[] out = new Deck[deckList.size()]; + deckList.toArray(out); + return out; + } + + public Map getBoosterDecks() { + return new HashMap(boosterMap); + } + + public void close() { + writeFile(); + } + + public void readFile() { + try { + deckList.clear(); + + File[] files; + files = dir.listFiles(dck); + for(File file:files) { + BufferedReader in = new BufferedReader(new FileReader(file)); + deckList.add(read(in)); + in.close(); + } + + boosterMap.clear(); + files = dir.listFiles(bdk); + for(File file:files) { + Deck[] d = new Deck[8]; + for(int i = 0; i < d.length; i++) { + BufferedReader in = new BufferedReader(new FileReader(new File(file, i + ".dck"))); + d[i] = read(in); + in.close(); + } + boosterMap.put(d[0].getName(), d); + } + } catch(IOException ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("DeckIO : read() error, " + ex.getMessage()); + } + } + + private Deck read(BufferedReader in) throws IOException { + String line; + + //read name + String name = in.readLine(); + if(name == null) throw new IOException("Unexpected end of file"); + + //read comments + String comment = null; + while((line = in.readLine()) != null && !line.equals("[general]")) { + if(comment == null) comment = line; + else comment += "\n" + line; + } + + //read deck type + String deckType = in.readLine(); + if(deckType == null) throw new IOException("Unexpected end of file"); + + Deck d = new Deck(deckType); + d.setName(name); + d.setComment(comment); + + //go to [main] + while((line = in.readLine()) != null && !line.equals("[main]")) + System.err.println("unexpected line: " + line); + if(line == null) throw new IOException("Unexpected end of file"); + + Pattern p = Pattern.compile("\\s*((\\d+)\\s+)?(.*?)\\s*"); + + //read main deck + while((line = in.readLine()) != null && !line.equals("[sideboard]")) { + Matcher m = p.matcher(line); + if(!m.matches()) throw new IOException("unexpected line: " + line); + String s = m.group(2); + int count = s == null? 1:parseInt(s); + + for(int i = 0; i < count; i++) { + d.addMain(m.group(3)); + } + } + if(line == null) throw new IOException("Unexpected end of file"); + + //read sideboard + while((line = in.readLine()) != null && line.length() != 0) { + Matcher m = p.matcher(line); + if(!m.matches()) throw new IOException("unexpected line: " + line); + String s = m.group(2); + int count = s == null? 1:parseInt(s); + for(int i = 0; i < count; i++) { + d.addSideboard(m.group(3)); + } + } + + return d; + } + + private String deriveFileName(String deckName) { + //skips all but the listed characters + return deckName.replaceAll("[^-_$#@.{[()]} a-zA-Z0-9]", ""); + } + + public void writeFile() { + try { + //store the files that do exist + List files = new ArrayList(); + files.addAll(asList(dir.listFiles(dck))); + + //save the files and remove them from the list + for(Deck deck:deckList) { + File f = new File(dir, deriveFileName(deck.getName()) + ".dck"); + files.remove(f); + BufferedWriter out = new BufferedWriter(new FileWriter(f)); + write(deck, out); + out.close(); + } + //delete the files that were not written out: the decks that were deleted + for(File file:files) + file.delete(); + + //store the files that do exist + files.clear(); + files.addAll(asList(dir.listFiles(bdk))); + + //save the files and remove them from the list + for(Entry e:boosterMap.entrySet()) { + File f = new File(dir, deriveFileName(e.getValue()[0].getName()) + ".bdk"); + f.mkdir(); + for(int i = 0; i < e.getValue().length; i++) { + BufferedWriter out = new BufferedWriter(new FileWriter(new File(f, i + ".dck"))); + write(e.getValue()[i], out); + out.close(); + } + } + //delete the files that were not written out: the decks that were deleted + for(File file:files) { + for(int i = 0; i < 8; i++) + new File(file, i + ".dck").delete(); + file.delete(); + } + } catch(IOException ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("DeckIO : write() error, " + ex.getMessage()); + } + } + + private void write(Deck d, BufferedWriter out) throws IOException { + out.write(format("%s%n", d.getName())); + if(d.getComment() != null) out.write(format("%s%n", d.getComment())); + out.write(format("%s%n", "[general]")); + out.write(format("%s%n", d.getDeckType())); + out.write(format("%s%n", "[main]")); + for(Entry e:count(d.getMain()).entrySet()) { + out.write(format("%d %s%n", e.getValue(), e.getKey())); + } + out.write(format("%s%n", "[sideboard]")); + for(Entry e:count(d.getSideboard()).entrySet()) { + out.write(format("%d %s%n", e.getValue(), e.getKey())); + } + } + + private Map count(List src) { + Map result = new HashMap(); + for(String s:src) { + Integer dstValue = result.get(s); + if(dstValue == null) result.put(s, 1); + else result.put(s, dstValue.intValue() + 1); + } + return result; + } +} diff --git a/src/forge/NewIO.java b/src/forge/NewIO.java index 5f3cd3a3b19..35b3072fe01 100644 --- a/src/forge/NewIO.java +++ b/src/forge/NewIO.java @@ -66,7 +66,7 @@ public class NewIO { private ObjectInputStream getReader() { try { - return new _ObjectInputStream(new FileInputStream(file)); + return new ObjectInputStream(new FileInputStream(file)); } catch(IOException ex) { ErrorViewer.showError(ex); throw new RuntimeException("IO : getReader() - error - " + ex); diff --git a/src/forge/OldDeckIO.java b/src/forge/OldDeckIO.java new file mode 100644 index 00000000000..73e74bc551f --- /dev/null +++ b/src/forge/OldDeckIO.java @@ -0,0 +1,202 @@ + +package forge; + + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import forge.error.ErrorViewer; + + +//reads and write Deck objects +public class OldDeckIO implements DeckIO { + private final File file; + private ArrayList deckList = new ArrayList(); + + //key is String of the humans deck + //data is Deck[] size of 8 + //humans deck is Deck[0] + private Map boosterMap = new HashMap(); + + public static void main(String[] args) { + Deck[] deck = new Deck[8]; + for(int i = 0; i < deck.length; i++) { + deck[i] = new Deck(Constant.GameType.Draft); + deck[i].setName("" + i); + } + + deck[0].addMain("Lantern Kami"); + + //DeckIO io = new DeckIO("booster-decks"); +// io.writeBoosterDeck(deck); +// io.close(); + +// io.deleteBoosterDeck("0"); +// System.out.println(io.getBoosterDecks().keySet().size()); +// io.close(); + } + + public OldDeckIO(String filename) { + this(new File(filename)); + } + + public OldDeckIO(File file) { + this.file = file; + + readFile(); + } + + public boolean isUnique(String deckName) { + Deck d; + for(int i = 0; i < deckList.size(); i++) { + d = deckList.get(i); + if(d.getName().equals(deckName)) return false; + } + return true; + } + + public boolean isUniqueDraft(String deckName) { + ArrayList key = new ArrayList(boosterMap.keySet()); + + for(int i = 0; i < key.size(); i++) { + if(key.get(i).equals(deckName)) return false; + } + return true; + } + + public boolean hasName(String deckName) { + ArrayList string = new ArrayList(); + + for(int i = 0; i < deckList.size(); i++) + string.add(deckList.get(i).toString()); + + Iterator it = boosterMap.keySet().iterator(); + while(it.hasNext()) + string.add(it.next().toString()); + + return string.contains(deckName); + } + + public Deck readDeck(String deckName) { + return deckList.get(findDeckIndex(deckName)); + } + + private int findDeckIndex(String deckName) { + int n = -1; + for(int i = 0; i < deckList.size(); i++) + if((deckList.get(i)).getName().equals(deckName)) n = i; + + if(n == -1) throw new RuntimeException("DeckIO : findDeckIndex() error, deck name not found - " + deckName); + + return n; + } + + public void writeDeck(Deck deck) { + if(deck.getDeckType().equals(Constant.GameType.Draft)) throw new RuntimeException( + "DeckIO : writeDeck() error, deck type is Draft"); + + deckList.add(deck); + } + + public void deleteDeck(String deckName) { + deckList.remove(findDeckIndex(deckName)); + } + + public Deck[] readBoosterDeck(String deckName) { + if(!boosterMap.containsKey(deckName)) throw new RuntimeException( + "DeckIO : readBoosterDeck() error, deck name not found - " + deckName); + + return boosterMap.get(deckName); + } + + public void writeBoosterDeck(Deck[] deck) { + checkBoosterDeck(deck); + + boosterMap.put(deck[0].toString(), deck); + }//writeBoosterDeck() + + public void deleteBoosterDeck(String deckName) { + if(!boosterMap.containsKey(deckName)) throw new RuntimeException( + "DeckIO : deleteBoosterDeck() error, deck name not found - " + deckName); + + boosterMap.remove(deckName); + } + + private void checkBoosterDeck(Deck[] deck) { + if(deck == null || deck.length != 8 || deck[0].getName().equals("") + || (!deck[0].getDeckType().equals(Constant.GameType.Draft))) { + throw new RuntimeException("DeckIO : checkBoosterDeck() error, invalid deck"); + } +// for(int i = 0; i < deck.length; i++) +// if(deck[i].getName().equals("")) +// throw new RuntimeException("DeckIO : checkBoosterDeck() error, deck does not have name - " +deck[i].getName()); + }//checkBoosterDeck() + + + public Deck[] getDecks() { + Deck[] out = new Deck[deckList.size()]; + deckList.toArray(out); + return out; + } + + public Map getBoosterDecks() { + return new HashMap(boosterMap); + } + + public void close() { + writeFile(); + } + + @SuppressWarnings("unchecked") + // ArrayList and Map have unchecked casts + private void readFile() { + try { +//~ + // Shouldn't ever get here, but just in case... + if(file == null) { + return; + } +//~ + if(!file.exists()) return; + + ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); + + deckList = (ArrayList) in.readObject(); + boosterMap = (Map) in.readObject(); + + in.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("DeckIO : read() error, " + ex); + } + } + + private void writeFile() { + try { +//~ + if(file == null) { + return; + } +//~ + if(!file.exists()) file.createNewFile(); + + ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file)); + + out.writeObject(deckList); + out.writeObject(boosterMap); + + out.flush(); + out.close(); + } catch(Exception ex) { + ErrorViewer.showError(ex); + throw new RuntimeException("DeckIO : write() error, " + ex.getMessage()); + } + } +}//DeckIO diff --git a/src/forge/QuestData.java b/src/forge/QuestData.java index 74106eae00d..6a79243afeb 100644 --- a/src/forge/QuestData.java +++ b/src/forge/QuestData.java @@ -195,7 +195,7 @@ public class QuestData implements NewConstants { static public QuestData loadData() { try { //read file "questData" - ObjectInputStream in = new _ObjectInputStream(new FileInputStream(ForgeProps.getFile(QUEST.DATA))); + ObjectInputStream in = new ObjectInputStream(new FileInputStream(ForgeProps.getFile(QUEST.DATA))); Object o = in.readObject(); in.close(); diff --git a/src/forge/_ObjectInputStream.java b/src/forge/_ObjectInputStream.java deleted file mode 100644 index 711294d54e6..00000000000 --- a/src/forge/_ObjectInputStream.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * _ObjectInputStream.java - * - * Created on 29.10.2009 - */ - -package forge; - - -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; - - -/** - * The class _ObjectInputStream. - * - * @version V0.0 29.10.2009 - * @author Clemens Koza - */ -public class _ObjectInputStream extends ObjectInputStream { - public _ObjectInputStream() throws IOException { - super(); - enableResolveObject(true); - } - - public _ObjectInputStream(InputStream is) throws IOException { - super(is); - enableResolveObject(true); - } - - @Override - protected Object resolveObject(Object obj) throws IOException { - Class c = obj.getClass().getComponentType(); - if(c != null && "Deck".equals(c.getName())) { - return new Deck[((Object[]) obj).length]; - } else return obj; - } -} diff --git a/src/forge/properties/NewConstants.java b/src/forge/properties/NewConstants.java index e9eddb81f94..e6106d3e240 100644 --- a/src/forge/properties/NewConstants.java +++ b/src/forge/properties/NewConstants.java @@ -22,6 +22,7 @@ public interface NewConstants { public static final String DECKS = "decks"; public static final String BOOSTER_DECKS = "booster-decks"; + public static final String NEW_DECKS = "decks-dir"; public static final String TOKENS = "tokens"; public static final String CARD_PICTURES = "card-pictures";