001package squidpony; 002 003import squidpony.store.json.JsonStorage; 004 005/** 006 * Helps games store information in libGDX's Preferences class as Strings, then get it back out. 007 * Created by Tommy Ettinger on 9/16/2016. 008 */ 009public class SquidStorage extends JsonStorage { 010 /** 011 * Please don't use this constructor if possible; it simply calls {@link #SquidStorage(String)} with the constant 012 * String "nameless". This could easily overlap with other files/sections in Preferences, so you should always 013 * prefer giving a String argument to the constructor, typically the name of the game. 014 * @see #SquidStorage(String) the recommended constructor to use 015 */ 016 public SquidStorage() 017 { 018 super("nameless"); 019 } 020 021 /** 022 * Creates a SquidStorage with the given fileName to save using Preferences from libGDX. The name should generally 023 * be the name of this game or application, and must be a valid name for a file (so no slashes, backslashes, colons, 024 * semicolons, or commas for certain, and other non-alphanumeric characters are also probably invalid). You should 025 * not assume anything is present in the Preferences storage unless you have put it there, and this applies doubly 026 * to games or applications other than your own; you should avoid values for fileName that might overlap with 027 * another game's Preferences values. 028 * <br> 029 * To organize saved data into sub-sections, you specify logical units (like different players' saved games) with a 030 * String outerName when you call {@link #store(String)}, and can further distinguish data under the outerName when 031 * you call {@link #put(String, Object)} to put each individual item into the saved storage with its own innerName. 032 * <br> 033 * Calling this also sets up custom serializers for several important types in SquidLib; char[][], OrderedMap, 034 * IntDoubleOrderedMap, FakeLanguageGen, GreasedRegion, and notably Pattern from RegExodus all have smaller 035 * serialized representations than the default. OrderedMap allows non-String keys, which gets around a limitation in 036 * JSON maps normally, and both FakeLanguageGen and Pattern are amazingly smaller with the custom representation. 037 * The custom char[][] representation is about half the normal size by omitting commas after each char. 038 * @param fileName the valid file name to create or open from Preferences; typically the name of the game/app. 039 */ 040 public SquidStorage(final String fileName) 041 { 042 super(fileName); 043 } 044 /** 045 * Creates a SquidStorage with the given fileName to save using Preferences from libGDX. The name should generally 046 * be the name of this game or application, and must be a valid name for a file (so no slashes, backslashes, colons, 047 * semicolons, or commas for certain, and other non-alphanumeric characters are also probably invalid). You should 048 * not assume anything is present in the Preferences storage unless you have put it there, and this applies doubly 049 * to games or applications other than your own; you should avoid values for fileName that might overlap with 050 * another game's Preferences values. This constructor also allows you to specify a "garble" String; if this is 051 * non-null, it will be used as a key to obfuscate the output and de-obfuscate the loaded input using fairly basic 052 * methods. If garble is null, it is ignored. 053 * <br> 054 * To organize saved data into sub-sections, you specify logical units (like different players' saved games) with a 055 * String outerName when you call {@link #store(String)}, and can further distinguish data under the outerName when 056 * you call {@link #put(String, Object)} to put each individual item into the saved storage with its own innerName. 057 * <br> 058 * Calling this also sets up custom serializers for several important types in SquidLib; char[][], OrderedMap, 059 * IntDoubleOrderedMap, FakeLanguageGen, GreasedRegion, and notably Pattern from RegExodus all have smaller 060 * serialized representations than the default. OrderedMap allows non-String keys, which gets around a limitation in 061 * JSON maps normally, and both FakeLanguageGen and Pattern are amazingly smaller with the custom representation. 062 * The custom char[][] representation is about half the normal size by omitting commas after each char. 063 * @param fileName the valid file name to create or open from Preferences; typically the name of the game/app. 064 * @param garble a String that will be used as a key to obfuscate the saved output if non-null 065 */ 066 public SquidStorage(final String fileName, final String garble) 067 { 068 super(fileName, garble); 069 } 070 /** 071 * Creates a SquidStorage with the given fileName to save using Preferences from libGDX. The name should generally 072 * be the name of this game or application, and must be a valid name for a file (so no slashes, backslashes, colons, 073 * semicolons, or commas for certain, and other non-alphanumeric characters are also probably invalid). You should 074 * not assume anything is present in the Preferences storage unless you have put it there, and this applies doubly 075 * to games or applications other than your own; you should avoid values for fileName that might overlap with 076 * another game's Preferences values. This constructor also allows you to specify a "garble" long array; if this is 077 * non-empty, it will be used as a key to obfuscate the output and de-obfuscate the loaded input using fairly basic 078 * methods. If garble is null or empty, it is ignored. 079 * <br> 080 * To organize saved data into sub-sections, you specify logical units (like different players' saved games) with a 081 * String outerName when you call {@link #store(String)}, and can further distinguish data under the outerName when 082 * you call {@link #put(String, Object)} to put each individual item into the saved storage with its own innerName. 083 * <br> 084 * Calling this also sets up custom serializers for several important types in SquidLib; char[][], OrderedMap, 085 * IntDoubleOrderedMap, FakeLanguageGen, GreasedRegion, and notably Pattern from RegExodus all have smaller 086 * serialized representations than the default. OrderedMap allows non-String keys, which gets around a limitation in 087 * JSON maps normally, and both FakeLanguageGen and Pattern are amazingly smaller with the custom representation. 088 * The custom char[][] representation is about half the normal size by omitting commas after each char. 089 * @param fileName the valid file name to create or open from Preferences; typically the name of the game/app. 090 * @param garble a long array that will be used as a key to obfuscate the saved output if non-null 091 */ 092 public SquidStorage(final String fileName, final long[] garble) 093 { 094 super(fileName, garble); 095 } 096 /** 097 * Prepares to store the Object {@code o} to be retrieved with {@code innerName} in the current group of objects. 098 * Does not write to a permanent location until {@link #store(String)} is called. The innerName used to store an 099 * object is required to get it back again, and can also be used to remove it before storing (or storing again). 100 * @param innerName one of the two Strings needed to retrieve this later 101 * @param o the Object to prepare to store 102 * @return this for chaining 103 */ 104 public SquidStorage put(String innerName, Object o) 105 { 106 super.put(innerName, o); 107 return this; 108 } 109 110 /** 111 * Actually stores all objects that had previously been prepared with {@link #put(String, Object)}, with 112 * {@code outerName} used as a key to retrieve any object in the current group. Flushes the preferences, making the 113 * changes permanent (until overwritten), but does not change the current group (you may want to call this method 114 * again with additional items in the current group, and that would simply involve calling put() again). If you want 115 * to clear the current group, use {@link #clear()}. If you want to remove just one object from the current group, 116 * use {@link #remove(String)}. 117 * @param outerName one of the two Strings needed to retrieve any of the objects in the current group 118 * @return this for chaining 119 */ 120 public SquidStorage store(String outerName) 121 { 122 super.store(outerName); 123 return this; 124 } 125 126 /** 127 * Gets a String representation of the data that would be saved when {@link #store(String)} is called. This can be 128 * useful for finding particularly problematic objects that require unnecessary space when serialized. 129 * @return a String that previews what would be stored permanently when {@link #store(String)} is called 130 */ 131 public String show() 132 { 133 return super.show(); 134 } 135 136 /** 137 * Clears the current group of objects; recommended if you intend to store under multiple outerName keys. 138 * @return this for chaining 139 */ 140 public SquidStorage clear() 141 { 142 super.clear(); 143 return this; 144 } 145 146 /** 147 * Removes one object from the current group by the {@code innerName} it was prepared with using 148 * {@link #put(String, Object)}. This does not affect already-stored objects unless {@link #store(String)} is called 149 * after this, in which case the new version of the current group, without the object this removed, is stored. 150 * @param innerName the String key used to put an object in the current group with {@link #put(String, Object)} 151 * @return this for chaining 152 */ 153 public SquidStorage remove(String innerName) 154 { 155 super.remove(innerName); 156 return this; 157 } 158 159 /** 160 * Gets an object from the storage by the given {@code outerName} key from {@link #store(String)} and 161 * {@code innerName} key from {@link #put(String, Object)}, and uses the class given by {@code type} for the 162 * returned value, assuming it matches the object that was originally put with those keys. If no such object is 163 * present, returns null. Results are undefined if {@code type} doesn't match the actual class of the stored object. 164 * @param outerName the key used to store the group of objects with {@link #store(String)} 165 * @param innerName the key used to store the specific object with {@link #put(String, Object)} 166 * @param type the class of the value; for a class like RNG, use {@code RNG.class}, but changed to fit 167 * @param <T> the type of the value to retrieve; if type was {@code RNG.class}, this would be {@code RNG} 168 * @return the retrieved value if successful, or null otherwise 169 */ 170 public <T> T get(String outerName, String innerName, Class<T> type) 171 { 172 return super.get(outerName, innerName, type); 173 } 174 175 /** 176 * Gets the approximate size of the currently-stored preferences. This assumes UTF-16 storage, which is the case for 177 * GWT's LocalStorage. Since GWT is restricted to the size the browser permits for LocalStorage, and this limit can 178 * be rather small (about 5 MB, sometimes more but not reliably), this method is especially useful there, but it may 179 * yield inaccurate sizes on other platforms that save Preferences data differently. 180 * @return the size, in bytes, of the already-stored preferences 181 */ 182 public int preferencesSize() 183 { 184 return super.preferencesSize(); 185 } 186 187}