Commit c2d5a299069eb51531c306409567859dee6f9947
1 parent
b98d2088
Add offline support to webprefs, closes #7
Showing
6 changed files
with
451 additions
and
79 deletions
src/client/java/com/mumfrey/liteloader/client/mixin/MixinSession.java
| ... | ... | @@ -5,8 +5,6 @@ |
| 5 | 5 | */ |
| 6 | 6 | package com.mumfrey.liteloader.client.mixin; |
| 7 | 7 | |
| 8 | -import java.util.UUID; | |
| 9 | - | |
| 10 | 8 | import org.spongepowered.asm.mixin.Mixin; |
| 11 | 9 | import org.spongepowered.asm.mixin.Shadow; |
| 12 | 10 | import org.spongepowered.asm.mixin.injection.At; |
| ... | ... | @@ -30,7 +28,6 @@ public abstract class MixinSession |
| 30 | 28 | )) |
| 31 | 29 | private void generateGameProfile(CallbackInfoReturnable<GameProfile> ci) |
| 32 | 30 | { |
| 33 | - UUID uuid = EntityPlayer.getUUID(new GameProfile((UUID)null, this.getUsername())); | |
| 34 | - ci.setReturnValue(new GameProfile(uuid, this.getUsername())); | |
| 31 | + ci.setReturnValue(new GameProfile(EntityPlayer.getOfflineUUID(this.getUsername()), this.getUsername())); | |
| 35 | 32 | } |
| 36 | 33 | } | ... | ... |
src/client/java/com/mumfrey/webprefs/AbstractWebPreferences.java
0 → 100644
| 1 | +package com.mumfrey.webprefs; | |
| 2 | + | |
| 3 | +import java.util.Set; | |
| 4 | +import java.util.UUID; | |
| 5 | + | |
| 6 | +import com.mumfrey.webprefs.interfaces.IWebPreferences; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * Common base class for online/offline web preferences | |
| 10 | + */ | |
| 11 | +abstract class AbstractWebPreferences implements IWebPreferences | |
| 12 | +{ | |
| 13 | + /** | |
| 14 | + * Our UUID | |
| 15 | + */ | |
| 16 | + protected final String uuid; | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * True if we are a private settings set | |
| 20 | + */ | |
| 21 | + protected final boolean isPrivate; | |
| 22 | + | |
| 23 | + protected final boolean isReadOnly; | |
| 24 | + | |
| 25 | + AbstractWebPreferences(UUID uuid, boolean isPrivate, boolean isReadOnly) | |
| 26 | + { | |
| 27 | + this(uuid.toString(), isPrivate, isReadOnly); | |
| 28 | + } | |
| 29 | + | |
| 30 | + AbstractWebPreferences(String uuid, boolean isPrivate, boolean isReadOnly) | |
| 31 | + { | |
| 32 | + this.uuid = uuid; | |
| 33 | + this.isPrivate = isPrivate; | |
| 34 | + this.isReadOnly = isReadOnly; | |
| 35 | + } | |
| 36 | + | |
| 37 | + void onTick() | |
| 38 | + { | |
| 39 | + // stub for subclasses | |
| 40 | + } | |
| 41 | + | |
| 42 | + /* (non-Javadoc) | |
| 43 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences#getUUID() | |
| 44 | + */ | |
| 45 | + @Override | |
| 46 | + public final String getUUID() | |
| 47 | + { | |
| 48 | + return this.uuid; | |
| 49 | + } | |
| 50 | + | |
| 51 | + /* (non-Javadoc) | |
| 52 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences#isPrivate() | |
| 53 | + */ | |
| 54 | + @Override | |
| 55 | + public final boolean isPrivate() | |
| 56 | + { | |
| 57 | + return this.isPrivate; | |
| 58 | + } | |
| 59 | + | |
| 60 | + /* (non-Javadoc) | |
| 61 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences#isReadOnly() | |
| 62 | + */ | |
| 63 | + @Override | |
| 64 | + public final boolean isReadOnly() | |
| 65 | + { | |
| 66 | + return this.isReadOnly; | |
| 67 | + } | |
| 68 | + | |
| 69 | + /* (non-Javadoc) | |
| 70 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 71 | + * #request(java.lang.String) | |
| 72 | + */ | |
| 73 | + @Override | |
| 74 | + public void request(String key) | |
| 75 | + { | |
| 76 | + WebPreferences.validateKey(key); | |
| 77 | + } | |
| 78 | + | |
| 79 | + /* (non-Javadoc) | |
| 80 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 81 | + * #request(java.lang.String[]) | |
| 82 | + */ | |
| 83 | + @Override | |
| 84 | + public void request(String... keys) | |
| 85 | + { | |
| 86 | + if (keys == null || keys.length < 1) return; | |
| 87 | + if (keys.length == 1) this.request(keys[0]); | |
| 88 | + | |
| 89 | + for (String key : keys) | |
| 90 | + { | |
| 91 | + this.request(key); | |
| 92 | + } | |
| 93 | + } | |
| 94 | + | |
| 95 | + /* (non-Javadoc) | |
| 96 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 97 | + * #request(java.util.Set) | |
| 98 | + */ | |
| 99 | + @Override | |
| 100 | + public void request(Set<String> keys) | |
| 101 | + { | |
| 102 | + if (keys == null || keys.size() < 1) return; | |
| 103 | + | |
| 104 | + for (String key : keys) | |
| 105 | + { | |
| 106 | + this.request(key); | |
| 107 | + } | |
| 108 | + } | |
| 109 | + | |
| 110 | + /* (non-Javadoc) | |
| 111 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences#commit(boolean) | |
| 112 | + */ | |
| 113 | + @Override | |
| 114 | + public void commit(boolean force) | |
| 115 | + { | |
| 116 | + } | |
| 117 | + | |
| 118 | + /* (non-Javadoc) | |
| 119 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 120 | + * #set(java.lang.String, java.lang.String) | |
| 121 | + */ | |
| 122 | + @Override | |
| 123 | + public void set(String key, String value) | |
| 124 | + { | |
| 125 | + WebPreferences.validateKey(key); | |
| 126 | + } | |
| 127 | + | |
| 128 | + /* (non-Javadoc) | |
| 129 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 130 | + * #remove(java.lang.String) | |
| 131 | + */ | |
| 132 | + @Override | |
| 133 | + public void remove(String key) | |
| 134 | + { | |
| 135 | + this.set(key, ""); | |
| 136 | + } | |
| 137 | +} | ... | ... |
src/client/java/com/mumfrey/webprefs/DummyOfflineWebPreferences.java
0 → 100644
| 1 | +package com.mumfrey.webprefs; | |
| 2 | + | |
| 3 | +import java.util.UUID; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * No-op webpreferences set which is returned for nonlocal players when the | |
| 7 | + * client is running in offline mode. | |
| 8 | + */ | |
| 9 | +public class DummyOfflineWebPreferences extends AbstractWebPreferences | |
| 10 | +{ | |
| 11 | + DummyOfflineWebPreferences(UUID uuid, boolean isPrivate, boolean isReadOnly) | |
| 12 | + { | |
| 13 | + this(uuid.toString(), isPrivate, isReadOnly); | |
| 14 | + } | |
| 15 | + | |
| 16 | + public DummyOfflineWebPreferences(String uuid, boolean isPrivate, boolean isReadOnly) | |
| 17 | + { | |
| 18 | + super(uuid, isPrivate, isReadOnly); | |
| 19 | + } | |
| 20 | + | |
| 21 | + /* (non-Javadoc) | |
| 22 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences#poll() | |
| 23 | + */ | |
| 24 | + @Override | |
| 25 | + public void poll() | |
| 26 | + { | |
| 27 | + } | |
| 28 | + | |
| 29 | + /* (non-Javadoc) | |
| 30 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 31 | + * #has(java.lang.String) | |
| 32 | + */ | |
| 33 | + @Override | |
| 34 | + public boolean has(String key) | |
| 35 | + { | |
| 36 | + WebPreferences.validateKey(key); | |
| 37 | + return false; | |
| 38 | + } | |
| 39 | + | |
| 40 | + /* (non-Javadoc) | |
| 41 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 42 | + * #get(java.lang.String) | |
| 43 | + */ | |
| 44 | + @Override | |
| 45 | + public String get(String key) | |
| 46 | + { | |
| 47 | + WebPreferences.validateKey(key); | |
| 48 | + return ""; | |
| 49 | + } | |
| 50 | + | |
| 51 | + /* (non-Javadoc) | |
| 52 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 53 | + * #get(java.lang.String, java.lang.String) | |
| 54 | + */ | |
| 55 | + @Override | |
| 56 | + public String get(String key, String defaultValue) | |
| 57 | + { | |
| 58 | + WebPreferences.validateKey(key); | |
| 59 | + return defaultValue; | |
| 60 | + } | |
| 61 | +} | |
| 0 | 62 | \ No newline at end of file | ... | ... |
src/client/java/com/mumfrey/webprefs/OfflineWebPreferences.java
0 → 100644
| 1 | +package com.mumfrey.webprefs; | |
| 2 | + | |
| 3 | +import java.io.File; | |
| 4 | +import java.io.FileReader; | |
| 5 | +import java.io.FileWriter; | |
| 6 | +import java.io.IOException; | |
| 7 | +import java.util.HashMap; | |
| 8 | +import java.util.Map; | |
| 9 | +import java.util.UUID; | |
| 10 | + | |
| 11 | +import com.google.gson.Gson; | |
| 12 | +import com.google.gson.GsonBuilder; | |
| 13 | +import com.mumfrey.liteloader.core.LiteLoader; | |
| 14 | +import com.mumfrey.webprefs.exceptions.ReadOnlyPreferencesException; | |
| 15 | + | |
| 16 | +/** | |
| 17 | + * Surrogate preferences returned for a local offline player, allows offline | |
| 18 | + * players to use the webpreferences system with preferences just being stored | |
| 19 | + * locally. | |
| 20 | + */ | |
| 21 | +class OfflineWebPreferences extends DummyOfflineWebPreferences | |
| 22 | +{ | |
| 23 | + /** | |
| 24 | + * Gson instance for serialisation/deserialisation to local JSON file | |
| 25 | + */ | |
| 26 | + private static final Gson gson = new GsonBuilder().setPrettyPrinting().create(); | |
| 27 | + | |
| 28 | + /** | |
| 29 | + * Maximum commit-to-disk rate in ticks | |
| 30 | + */ | |
| 31 | + private static final int COMMIT_RATE = 20 * 3; | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * JSON file | |
| 35 | + */ | |
| 36 | + private final File store; | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * Local KV store | |
| 40 | + */ | |
| 41 | + final Map<String, String> prefs; | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * Tick number for write throttling | |
| 45 | + */ | |
| 46 | + private int tickNumber; | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * Flag indicating serialisation to disk is required | |
| 50 | + */ | |
| 51 | + private boolean isDirty; | |
| 52 | + | |
| 53 | + OfflineWebPreferences(UUID uuid, boolean isPrivate, boolean isReadOnly) | |
| 54 | + { | |
| 55 | + this(uuid.toString(), isPrivate, isReadOnly); | |
| 56 | + } | |
| 57 | + | |
| 58 | + OfflineWebPreferences(String uuid, boolean isPrivate, boolean isReadOnly) | |
| 59 | + { | |
| 60 | + super(uuid, isPrivate, isReadOnly); | |
| 61 | + | |
| 62 | + this.store = new File(LiteLoader.getCommonConfigFolder(), String.format("%s.%sprefs.json", uuid, isPrivate ? "private" : "")); | |
| 63 | + this.prefs = this.loadValues(); | |
| 64 | + } | |
| 65 | + | |
| 66 | + @SuppressWarnings("unchecked") | |
| 67 | + private Map<String, String> loadValues() | |
| 68 | + { | |
| 69 | + if (this.store.isFile()) | |
| 70 | + { | |
| 71 | + FileReader reader = null; | |
| 72 | + | |
| 73 | + try | |
| 74 | + { | |
| 75 | + reader = new FileReader(this.store); | |
| 76 | + return OfflineWebPreferences.gson.fromJson(reader, Map.class); | |
| 77 | + } | |
| 78 | + catch (IOException ex) {} | |
| 79 | + finally | |
| 80 | + { | |
| 81 | + try | |
| 82 | + { | |
| 83 | + if (reader != null) reader.close(); | |
| 84 | + } | |
| 85 | + catch (IOException ex) {} | |
| 86 | + } | |
| 87 | + } | |
| 88 | + | |
| 89 | + return new HashMap<String, String>(); | |
| 90 | + } | |
| 91 | + | |
| 92 | + private void saveValues() | |
| 93 | + { | |
| 94 | + FileWriter writer = null; | |
| 95 | + | |
| 96 | + try | |
| 97 | + { | |
| 98 | + writer = new FileWriter(this.store); | |
| 99 | + OfflineWebPreferences.gson.toJson(this.prefs, writer); | |
| 100 | + } | |
| 101 | + catch (IOException ex) {} | |
| 102 | + finally | |
| 103 | + { | |
| 104 | + try | |
| 105 | + { | |
| 106 | + if (writer != null) writer.close(); | |
| 107 | + } | |
| 108 | + catch (IOException ex) {} | |
| 109 | + } | |
| 110 | + } | |
| 111 | + | |
| 112 | + @Override | |
| 113 | + void onTick() | |
| 114 | + { | |
| 115 | + if (this.tickNumber++ > OfflineWebPreferences.COMMIT_RATE && this.isDirty) | |
| 116 | + { | |
| 117 | + this.isDirty = false; | |
| 118 | + this.tickNumber = 0; | |
| 119 | + this.saveValues(); | |
| 120 | + } | |
| 121 | + } | |
| 122 | + | |
| 123 | + @Override | |
| 124 | + public void request(String key) | |
| 125 | + { | |
| 126 | + WebPreferences.validateKey(key); | |
| 127 | + if (!this.prefs.containsKey(key)) | |
| 128 | + { | |
| 129 | + this.prefs.put(key, ""); | |
| 130 | + } | |
| 131 | + } | |
| 132 | + | |
| 133 | + /* (non-Javadoc) | |
| 134 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences#commit(boolean) | |
| 135 | + */ | |
| 136 | + @Override | |
| 137 | + public void commit(boolean force) | |
| 138 | + { | |
| 139 | + this.isDirty = true; | |
| 140 | + } | |
| 141 | + | |
| 142 | + /* (non-Javadoc) | |
| 143 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 144 | + * #has(java.lang.String) | |
| 145 | + */ | |
| 146 | + @Override | |
| 147 | + public boolean has(String key) | |
| 148 | + { | |
| 149 | + WebPreferences.validateKey(key); | |
| 150 | + return this.prefs.containsKey(key); | |
| 151 | + } | |
| 152 | + | |
| 153 | + /* (non-Javadoc) | |
| 154 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 155 | + * #get(java.lang.String) | |
| 156 | + */ | |
| 157 | + @Override | |
| 158 | + public String get(String key) | |
| 159 | + { | |
| 160 | + return this.get(key, ""); | |
| 161 | + } | |
| 162 | + | |
| 163 | + /* (non-Javadoc) | |
| 164 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 165 | + * #get(java.lang.String, java.lang.String) | |
| 166 | + */ | |
| 167 | + @Override | |
| 168 | + public String get(String key, String defaultValue) | |
| 169 | + { | |
| 170 | + WebPreferences.validateKey(key); | |
| 171 | + String value = this.prefs.get(key); | |
| 172 | + return value != null ? value : defaultValue; | |
| 173 | + } | |
| 174 | + | |
| 175 | + /* (non-Javadoc) | |
| 176 | + * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 177 | + * #set(java.lang.String, java.lang.String) | |
| 178 | + */ | |
| 179 | + @Override | |
| 180 | + public void set(String key, String value) | |
| 181 | + { | |
| 182 | + if (this.isReadOnly()) | |
| 183 | + { | |
| 184 | + throw new ReadOnlyPreferencesException("Preference collection for " + this.uuid + " is read-only"); | |
| 185 | + } | |
| 186 | + | |
| 187 | + WebPreferences.validateKV(key, value); | |
| 188 | + | |
| 189 | + this.prefs.put(key, value); | |
| 190 | + this.isDirty = true; | |
| 191 | + } | |
| 192 | +} | ... | ... |
src/client/java/com/mumfrey/webprefs/WebPreferences.java
| ... | ... | @@ -4,6 +4,7 @@ import java.util.HashMap; |
| 4 | 4 | import java.util.HashSet; |
| 5 | 5 | import java.util.Map; |
| 6 | 6 | import java.util.Set; |
| 7 | +import java.util.UUID; | |
| 7 | 8 | import java.util.concurrent.ConcurrentHashMap; |
| 8 | 9 | import java.util.regex.Pattern; |
| 9 | 10 | |
| ... | ... | @@ -12,11 +13,10 @@ import com.mumfrey.webprefs.exceptions.InvalidKeyException; |
| 12 | 13 | import com.mumfrey.webprefs.exceptions.InvalidValueException; |
| 13 | 14 | import com.mumfrey.webprefs.exceptions.ReadOnlyPreferencesException; |
| 14 | 15 | import com.mumfrey.webprefs.framework.RequestFailureReason; |
| 15 | -import com.mumfrey.webprefs.interfaces.IWebPreferences; | |
| 16 | 16 | import com.mumfrey.webprefs.interfaces.IWebPreferencesClient; |
| 17 | 17 | import com.mumfrey.webprefs.interfaces.IWebPreferencesProvider; |
| 18 | 18 | |
| 19 | -class WebPreferences implements IWebPreferences | |
| 19 | +class WebPreferences extends AbstractWebPreferences | |
| 20 | 20 | { |
| 21 | 21 | /** |
| 22 | 22 | * The update frequency to use when operating normally, this is the |
| ... | ... | @@ -104,18 +104,6 @@ class WebPreferences implements IWebPreferences |
| 104 | 104 | private final IWebPreferencesClient client; |
| 105 | 105 | |
| 106 | 106 | /** |
| 107 | - * Our UUID | |
| 108 | - */ | |
| 109 | - protected final String uuid; | |
| 110 | - | |
| 111 | - /** | |
| 112 | - * True if we are a private settings set | |
| 113 | - */ | |
| 114 | - protected final boolean isPrivate; | |
| 115 | - | |
| 116 | - protected final boolean isReadOnly; | |
| 117 | - | |
| 118 | - /** | |
| 119 | 107 | * Current key/value pairs |
| 120 | 108 | */ |
| 121 | 109 | protected final Map<String, String> prefs = new ConcurrentHashMap<String, String>(); |
| ... | ... | @@ -149,61 +137,30 @@ class WebPreferences implements IWebPreferences |
| 149 | 137 | private volatile int updateCheckTimer = 1; |
| 150 | 138 | |
| 151 | 139 | protected int requestTimeoutTimer = 0; |
| 140 | + | |
| 141 | + WebPreferences(IWebPreferencesProvider provider, UUID uuid, boolean isPrivate, boolean isReadOnly) | |
| 142 | + { | |
| 143 | + this(provider, uuid.toString(), isPrivate, isReadOnly); | |
| 144 | + } | |
| 152 | 145 | |
| 153 | 146 | WebPreferences(IWebPreferencesProvider provider, String uuid, boolean isPrivate, boolean isReadOnly) |
| 154 | 147 | { |
| 148 | + super(uuid, isPrivate, isReadOnly); | |
| 155 | 149 | this.provider = provider; |
| 156 | - this.uuid = uuid; | |
| 157 | - this.isPrivate = isPrivate; | |
| 158 | - this.isReadOnly = isReadOnly; | |
| 159 | 150 | this.client = new Client(); |
| 160 | 151 | } |
| 161 | 152 | |
| 162 | - /* (non-Javadoc) | |
| 163 | - * @see com.mumfrey.webprefs.interfaces.IWebPreferences#getUUID() | |
| 164 | - */ | |
| 165 | - @Override | |
| 166 | - public String getUUID() | |
| 167 | - { | |
| 168 | - return this.uuid; | |
| 169 | - } | |
| 170 | - | |
| 171 | - /* (non-Javadoc) | |
| 172 | - * @see com.mumfrey.webprefs.interfaces.IWebPreferences#isPrivate() | |
| 173 | - */ | |
| 174 | - @Override | |
| 175 | - public boolean isPrivate() | |
| 176 | - { | |
| 177 | - return this.isPrivate; | |
| 178 | - } | |
| 179 | - | |
| 180 | - /* (non-Javadoc) | |
| 181 | - * @see com.mumfrey.webprefs.interfaces.IWebPreferences#isReadOnly() | |
| 182 | - */ | |
| 183 | 153 | @Override |
| 184 | - public boolean isReadOnly() | |
| 185 | - { | |
| 186 | - return this.isReadOnly; | |
| 187 | - } | |
| 188 | - | |
| 189 | 154 | void onTick() |
| 190 | 155 | { |
| 191 | - if (this.updateCheckTimer > 0) | |
| 156 | + if (this.updateCheckTimer > 0 && --this.updateCheckTimer < 1) | |
| 192 | 157 | { |
| 193 | - this.updateCheckTimer--; | |
| 194 | - if (this.updateCheckTimer < 1) | |
| 195 | - { | |
| 196 | - this.update(); | |
| 197 | - } | |
| 158 | + this.update(); | |
| 198 | 159 | } |
| 199 | 160 | |
| 200 | - if (this.requestTimeoutTimer > 0) | |
| 161 | + if (this.requestTimeoutTimer > 0 && --this.requestTimeoutTimer < 1) | |
| 201 | 162 | { |
| 202 | - this.requestTimeoutTimer--; | |
| 203 | - if (this.requestTimeoutTimer < 1) | |
| 204 | - { | |
| 205 | - this.handleTimeout(); | |
| 206 | - } | |
| 163 | + this.handleTimeout(); | |
| 207 | 164 | } |
| 208 | 165 | } |
| 209 | 166 | |
| ... | ... | @@ -449,16 +406,6 @@ class WebPreferences implements IWebPreferences |
| 449 | 406 | } |
| 450 | 407 | } |
| 451 | 408 | |
| 452 | - /* (non-Javadoc) | |
| 453 | - * @see com.mumfrey.webprefs.interfaces.IWebPreferences | |
| 454 | - * #remove(java.lang.String) | |
| 455 | - */ | |
| 456 | - @Override | |
| 457 | - public void remove(String key) | |
| 458 | - { | |
| 459 | - this.set(key, ""); | |
| 460 | - } | |
| 461 | - | |
| 462 | 409 | /** |
| 463 | 410 | * Add a key to the current request set, the key will be requested from the |
| 464 | 411 | * server on the next {@link #update()} |
| ... | ... | @@ -563,7 +510,7 @@ class WebPreferences implements IWebPreferences |
| 563 | 510 | /** |
| 564 | 511 | * @param key |
| 565 | 512 | */ |
| 566 | - protected static final void validateKey(String key) | |
| 513 | + protected static void validateKey(String key) | |
| 567 | 514 | { |
| 568 | 515 | if (key == null || !WebPreferences.keyPattern.matcher(key).matches()) |
| 569 | 516 | { |
| ... | ... | @@ -575,7 +522,7 @@ class WebPreferences implements IWebPreferences |
| 575 | 522 | * @param key |
| 576 | 523 | * @param value |
| 577 | 524 | */ |
| 578 | - protected static final void validateKV(String key, String value) | |
| 525 | + protected static void validateKV(String key, String value) | |
| 579 | 526 | { |
| 580 | 527 | WebPreferences.validateKey(key); |
| 581 | 528 | ... | ... |
src/client/java/com/mumfrey/webprefs/WebPreferencesManager.java
| ... | ... | @@ -130,7 +130,7 @@ public final class WebPreferencesManager |
| 130 | 130 | /** |
| 131 | 131 | * All preference sets, for iteration purposes |
| 132 | 132 | */ |
| 133 | - private final List<WebPreferences> allPreferences = new LinkedList<WebPreferences>(); | |
| 133 | + private final List<AbstractWebPreferences> allPreferences = new LinkedList<AbstractWebPreferences>(); | |
| 134 | 134 | |
| 135 | 135 | /** |
| 136 | 136 | * All public preference sets, mapped by UUID |
| ... | ... | @@ -152,7 +152,7 @@ public final class WebPreferencesManager |
| 152 | 152 | { |
| 153 | 153 | this.provider.onTick(); |
| 154 | 154 | |
| 155 | - for (WebPreferences prefs : this.allPreferences) | |
| 155 | + for (AbstractWebPreferences prefs : this.allPreferences) | |
| 156 | 156 | { |
| 157 | 157 | try |
| 158 | 158 | { |
| ... | ... | @@ -164,7 +164,7 @@ public final class WebPreferencesManager |
| 164 | 164 | |
| 165 | 165 | void onJoinGame() |
| 166 | 166 | { |
| 167 | - for (WebPreferences prefs : this.allPreferences) | |
| 167 | + for (AbstractWebPreferences prefs : this.allPreferences) | |
| 168 | 168 | { |
| 169 | 169 | try |
| 170 | 170 | { |
| ... | ... | @@ -176,7 +176,9 @@ public final class WebPreferencesManager |
| 176 | 176 | |
| 177 | 177 | |
| 178 | 178 | /** |
| 179 | - * Get a public or private preferences collection for the local player | |
| 179 | + * Get a public or private preferences collection for the local player. If | |
| 180 | + * the game is running in offline mode, a local preference collection is | |
| 181 | + * returned instead. | |
| 180 | 182 | * |
| 181 | 183 | * @param privatePrefs true to fetch the player's private preferences, false |
| 182 | 184 | * to fetch public preferences |
| ... | ... | @@ -184,11 +186,21 @@ public final class WebPreferencesManager |
| 184 | 186 | */ |
| 185 | 187 | public IWebPreferences getLocalPreferences(boolean privatePrefs) |
| 186 | 188 | { |
| 187 | - return this.getPreferences(this.session.getPlayerID(), privatePrefs); | |
| 189 | + try | |
| 190 | + { | |
| 191 | + return this.getPreferences(this.session.getPlayerID(), privatePrefs); | |
| 192 | + } | |
| 193 | + catch (InvalidUUIDException ex) | |
| 194 | + { | |
| 195 | + UUID offlineUUID = EntityPlayer.getOfflineUUID(this.session.getUsername()); | |
| 196 | + return this.getOfflinePreferences(offlineUUID, privatePrefs, false, false); | |
| 197 | + } | |
| 188 | 198 | } |
| 189 | 199 | |
| 190 | 200 | /** |
| 191 | - * Get a public preferences collection for the specified player. | |
| 201 | + * Get a public preferences collection for the specified player. If the game | |
| 202 | + * is running in offline mode, a dummy preference collection supporting no | |
| 203 | + * operations is returned instead. | |
| 192 | 204 | * |
| 193 | 205 | * @param player Player to fetch preferences for |
| 194 | 206 | * @param privatePrefs True to fetch the player's private preferences, false |
| ... | ... | @@ -198,7 +210,16 @@ public final class WebPreferencesManager |
| 198 | 210 | */ |
| 199 | 211 | public IWebPreferences getPreferences(EntityPlayer player) |
| 200 | 212 | { |
| 201 | - return this.getPreferences(player, false); | |
| 213 | + try | |
| 214 | + { | |
| 215 | + return this.getPreferences(player, false); | |
| 216 | + } | |
| 217 | + catch (InvalidUUIDException ex) | |
| 218 | + { | |
| 219 | + String playerName = player.getName(); | |
| 220 | + UUID offlineUUID = EntityPlayer.getOfflineUUID(playerName); | |
| 221 | + return this.getOfflinePreferences(offlineUUID, false, false, !playerName.equals(this.session.getUsername())); | |
| 222 | + } | |
| 202 | 223 | } |
| 203 | 224 | |
| 204 | 225 | /** |
| ... | ... | @@ -279,7 +300,6 @@ public final class WebPreferencesManager |
| 279 | 300 | uuid = this.sanitiseUUID(uuid); |
| 280 | 301 | |
| 281 | 302 | Map<String, IWebPreferences> preferences = privatePrefs ? this.preferencesPrivate : this.preferencesPublic; |
| 282 | - | |
| 283 | 303 | IWebPreferences prefs = preferences.get(uuid); |
| 284 | 304 | |
| 285 | 305 | if (prefs == null) |
| ... | ... | @@ -293,6 +313,24 @@ public final class WebPreferencesManager |
| 293 | 313 | return prefs; |
| 294 | 314 | } |
| 295 | 315 | |
| 316 | + private IWebPreferences getOfflinePreferences(UUID uuid, boolean privatePrefs, boolean readOnly, boolean dummy) | |
| 317 | + { | |
| 318 | + Map<String, IWebPreferences> preferences = privatePrefs ? this.preferencesPrivate : this.preferencesPublic; | |
| 319 | + IWebPreferences prefs = preferences.get(uuid); | |
| 320 | + | |
| 321 | + if (prefs == null) | |
| 322 | + { | |
| 323 | + AbstractWebPreferences newPrefs = dummy | |
| 324 | + ? new DummyOfflineWebPreferences(uuid, privatePrefs, readOnly) | |
| 325 | + : new OfflineWebPreferences(uuid, privatePrefs, readOnly); | |
| 326 | + this.allPreferences.add(newPrefs); | |
| 327 | + preferences.put(uuid.toString(), newPrefs); | |
| 328 | + prefs = newPrefs; | |
| 329 | + } | |
| 330 | + | |
| 331 | + return prefs; | |
| 332 | + } | |
| 333 | + | |
| 296 | 334 | private String sanitiseUUID(String uuid) |
| 297 | 335 | { |
| 298 | 336 | if (uuid == null) | ... | ... |