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,8 +5,6 @@ | ||
| 5 | */ | 5 | */ |
| 6 | package com.mumfrey.liteloader.client.mixin; | 6 | package com.mumfrey.liteloader.client.mixin; |
| 7 | 7 | ||
| 8 | -import java.util.UUID; | ||
| 9 | - | ||
| 10 | import org.spongepowered.asm.mixin.Mixin; | 8 | import org.spongepowered.asm.mixin.Mixin; |
| 11 | import org.spongepowered.asm.mixin.Shadow; | 9 | import org.spongepowered.asm.mixin.Shadow; |
| 12 | import org.spongepowered.asm.mixin.injection.At; | 10 | import org.spongepowered.asm.mixin.injection.At; |
| @@ -30,7 +28,6 @@ public abstract class MixinSession | @@ -30,7 +28,6 @@ public abstract class MixinSession | ||
| 30 | )) | 28 | )) |
| 31 | private void generateGameProfile(CallbackInfoReturnable<GameProfile> ci) | 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 | \ No newline at end of file | 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,6 +4,7 @@ import java.util.HashMap; | ||
| 4 | import java.util.HashSet; | 4 | import java.util.HashSet; |
| 5 | import java.util.Map; | 5 | import java.util.Map; |
| 6 | import java.util.Set; | 6 | import java.util.Set; |
| 7 | +import java.util.UUID; | ||
| 7 | import java.util.concurrent.ConcurrentHashMap; | 8 | import java.util.concurrent.ConcurrentHashMap; |
| 8 | import java.util.regex.Pattern; | 9 | import java.util.regex.Pattern; |
| 9 | 10 | ||
| @@ -12,11 +13,10 @@ import com.mumfrey.webprefs.exceptions.InvalidKeyException; | @@ -12,11 +13,10 @@ import com.mumfrey.webprefs.exceptions.InvalidKeyException; | ||
| 12 | import com.mumfrey.webprefs.exceptions.InvalidValueException; | 13 | import com.mumfrey.webprefs.exceptions.InvalidValueException; |
| 13 | import com.mumfrey.webprefs.exceptions.ReadOnlyPreferencesException; | 14 | import com.mumfrey.webprefs.exceptions.ReadOnlyPreferencesException; |
| 14 | import com.mumfrey.webprefs.framework.RequestFailureReason; | 15 | import com.mumfrey.webprefs.framework.RequestFailureReason; |
| 15 | -import com.mumfrey.webprefs.interfaces.IWebPreferences; | ||
| 16 | import com.mumfrey.webprefs.interfaces.IWebPreferencesClient; | 16 | import com.mumfrey.webprefs.interfaces.IWebPreferencesClient; |
| 17 | import com.mumfrey.webprefs.interfaces.IWebPreferencesProvider; | 17 | import com.mumfrey.webprefs.interfaces.IWebPreferencesProvider; |
| 18 | 18 | ||
| 19 | -class WebPreferences implements IWebPreferences | 19 | +class WebPreferences extends AbstractWebPreferences |
| 20 | { | 20 | { |
| 21 | /** | 21 | /** |
| 22 | * The update frequency to use when operating normally, this is the | 22 | * The update frequency to use when operating normally, this is the |
| @@ -104,18 +104,6 @@ class WebPreferences implements IWebPreferences | @@ -104,18 +104,6 @@ class WebPreferences implements IWebPreferences | ||
| 104 | private final IWebPreferencesClient client; | 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 | * Current key/value pairs | 107 | * Current key/value pairs |
| 120 | */ | 108 | */ |
| 121 | protected final Map<String, String> prefs = new ConcurrentHashMap<String, String>(); | 109 | protected final Map<String, String> prefs = new ConcurrentHashMap<String, String>(); |
| @@ -149,61 +137,30 @@ class WebPreferences implements IWebPreferences | @@ -149,61 +137,30 @@ class WebPreferences implements IWebPreferences | ||
| 149 | private volatile int updateCheckTimer = 1; | 137 | private volatile int updateCheckTimer = 1; |
| 150 | 138 | ||
| 151 | protected int requestTimeoutTimer = 0; | 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 | WebPreferences(IWebPreferencesProvider provider, String uuid, boolean isPrivate, boolean isReadOnly) | 146 | WebPreferences(IWebPreferencesProvider provider, String uuid, boolean isPrivate, boolean isReadOnly) |
| 154 | { | 147 | { |
| 148 | + super(uuid, isPrivate, isReadOnly); | ||
| 155 | this.provider = provider; | 149 | this.provider = provider; |
| 156 | - this.uuid = uuid; | ||
| 157 | - this.isPrivate = isPrivate; | ||
| 158 | - this.isReadOnly = isReadOnly; | ||
| 159 | this.client = new Client(); | 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 | @Override | 153 | @Override |
| 184 | - public boolean isReadOnly() | ||
| 185 | - { | ||
| 186 | - return this.isReadOnly; | ||
| 187 | - } | ||
| 188 | - | ||
| 189 | void onTick() | 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,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 | * Add a key to the current request set, the key will be requested from the | 410 | * Add a key to the current request set, the key will be requested from the |
| 464 | * server on the next {@link #update()} | 411 | * server on the next {@link #update()} |
| @@ -563,7 +510,7 @@ class WebPreferences implements IWebPreferences | @@ -563,7 +510,7 @@ class WebPreferences implements IWebPreferences | ||
| 563 | /** | 510 | /** |
| 564 | * @param key | 511 | * @param key |
| 565 | */ | 512 | */ |
| 566 | - protected static final void validateKey(String key) | 513 | + protected static void validateKey(String key) |
| 567 | { | 514 | { |
| 568 | if (key == null || !WebPreferences.keyPattern.matcher(key).matches()) | 515 | if (key == null || !WebPreferences.keyPattern.matcher(key).matches()) |
| 569 | { | 516 | { |
| @@ -575,7 +522,7 @@ class WebPreferences implements IWebPreferences | @@ -575,7 +522,7 @@ class WebPreferences implements IWebPreferences | ||
| 575 | * @param key | 522 | * @param key |
| 576 | * @param value | 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 | WebPreferences.validateKey(key); | 527 | WebPreferences.validateKey(key); |
| 581 | 528 |
src/client/java/com/mumfrey/webprefs/WebPreferencesManager.java
| @@ -130,7 +130,7 @@ public final class WebPreferencesManager | @@ -130,7 +130,7 @@ public final class WebPreferencesManager | ||
| 130 | /** | 130 | /** |
| 131 | * All preference sets, for iteration purposes | 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 | * All public preference sets, mapped by UUID | 136 | * All public preference sets, mapped by UUID |
| @@ -152,7 +152,7 @@ public final class WebPreferencesManager | @@ -152,7 +152,7 @@ public final class WebPreferencesManager | ||
| 152 | { | 152 | { |
| 153 | this.provider.onTick(); | 153 | this.provider.onTick(); |
| 154 | 154 | ||
| 155 | - for (WebPreferences prefs : this.allPreferences) | 155 | + for (AbstractWebPreferences prefs : this.allPreferences) |
| 156 | { | 156 | { |
| 157 | try | 157 | try |
| 158 | { | 158 | { |
| @@ -164,7 +164,7 @@ public final class WebPreferencesManager | @@ -164,7 +164,7 @@ public final class WebPreferencesManager | ||
| 164 | 164 | ||
| 165 | void onJoinGame() | 165 | void onJoinGame() |
| 166 | { | 166 | { |
| 167 | - for (WebPreferences prefs : this.allPreferences) | 167 | + for (AbstractWebPreferences prefs : this.allPreferences) |
| 168 | { | 168 | { |
| 169 | try | 169 | try |
| 170 | { | 170 | { |
| @@ -176,7 +176,9 @@ public final class WebPreferencesManager | @@ -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 | * @param privatePrefs true to fetch the player's private preferences, false | 183 | * @param privatePrefs true to fetch the player's private preferences, false |
| 182 | * to fetch public preferences | 184 | * to fetch public preferences |
| @@ -184,11 +186,21 @@ public final class WebPreferencesManager | @@ -184,11 +186,21 @@ public final class WebPreferencesManager | ||
| 184 | */ | 186 | */ |
| 185 | public IWebPreferences getLocalPreferences(boolean privatePrefs) | 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 | * @param player Player to fetch preferences for | 205 | * @param player Player to fetch preferences for |
| 194 | * @param privatePrefs True to fetch the player's private preferences, false | 206 | * @param privatePrefs True to fetch the player's private preferences, false |
| @@ -198,7 +210,16 @@ public final class WebPreferencesManager | @@ -198,7 +210,16 @@ public final class WebPreferencesManager | ||
| 198 | */ | 210 | */ |
| 199 | public IWebPreferences getPreferences(EntityPlayer player) | 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,7 +300,6 @@ public final class WebPreferencesManager | ||
| 279 | uuid = this.sanitiseUUID(uuid); | 300 | uuid = this.sanitiseUUID(uuid); |
| 280 | 301 | ||
| 281 | Map<String, IWebPreferences> preferences = privatePrefs ? this.preferencesPrivate : this.preferencesPublic; | 302 | Map<String, IWebPreferences> preferences = privatePrefs ? this.preferencesPrivate : this.preferencesPublic; |
| 282 | - | ||
| 283 | IWebPreferences prefs = preferences.get(uuid); | 303 | IWebPreferences prefs = preferences.get(uuid); |
| 284 | 304 | ||
| 285 | if (prefs == null) | 305 | if (prefs == null) |
| @@ -293,6 +313,24 @@ public final class WebPreferencesManager | @@ -293,6 +313,24 @@ public final class WebPreferencesManager | ||
| 293 | return prefs; | 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 | private String sanitiseUUID(String uuid) | 334 | private String sanitiseUUID(String uuid) |
| 297 | { | 335 | { |
| 298 | if (uuid == null) | 336 | if (uuid == null) |