forked from VazkiiMods/Patchouli
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Manually load and save PersistentData, and make it more robust to mal…
…formed data
- Loading branch information
1 parent
4640df3
commit e355d85
Showing
8 changed files
with
118 additions
and
78 deletions.
There are no files selected for viewing
140 changes: 111 additions & 29 deletions
140
Xplat/src/main/java/vazkii/patchouli/client/base/PersistentData.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,74 +1,156 @@ | ||
package vazkii.patchouli.client.base; | ||
|
||
import com.google.gson.annotations.SerializedName; | ||
import com.google.common.base.Charsets; | ||
import com.google.gson.JsonArray; | ||
import com.google.gson.JsonObject; | ||
|
||
import net.minecraft.resources.ResourceLocation; | ||
import net.minecraft.util.GsonHelper; | ||
|
||
import vazkii.patchouli.api.PatchouliAPI; | ||
import vazkii.patchouli.client.book.BookEntry; | ||
import vazkii.patchouli.common.book.Book; | ||
import vazkii.patchouli.common.util.SerializationUtil; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.NoSuchFileException; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public final class PersistentData { | ||
|
||
private static File saveFile; | ||
private static final Path saveFile = Paths.get("patchouli_data.json"); | ||
|
||
public static DataHolder data; | ||
public static DataHolder data = new DataHolder(new JsonObject()); | ||
|
||
public static void setup() { | ||
saveFile = new File("patchouli_data.json"); | ||
load(); | ||
} | ||
|
||
public static void load() { | ||
data = SerializationUtil.loadFromFile(saveFile, DataHolder.class, DataHolder::new); | ||
try (var r = Files.newBufferedReader(saveFile, Charsets.UTF_8)) { | ||
var root = SerializationUtil.RAW_GSON.fromJson(r, JsonObject.class); | ||
data = new DataHolder(root); | ||
} catch (IOException e) { | ||
if (!(e instanceof NoSuchFileException)) { | ||
PatchouliAPI.LOGGER.warn("Unable to load patchouli_data.json, replacing with default", e); | ||
} | ||
data = new DataHolder(new JsonObject()); | ||
save(); | ||
} catch (Exception e) { | ||
PatchouliAPI.LOGGER.warn("Corrupted patchouli_data.json, replacing with default", e); | ||
data = new DataHolder(new JsonObject()); | ||
save(); | ||
} | ||
} | ||
|
||
public static void save() { | ||
SerializationUtil.saveToFile(SerializationUtil.PRETTY_GSON, saveFile, DataHolder.class, data); | ||
var json = data.serialize(); | ||
try (var w = Files.newBufferedWriter(saveFile, Charsets.UTF_8)) { | ||
SerializationUtil.PRETTY_GSON.toJson(json, w); | ||
} catch (IOException e) { | ||
PatchouliAPI.LOGGER.warn("Unable to save patchouli_data.json", e); | ||
} | ||
} | ||
|
||
public static final class DataHolder { | ||
public int bookGuiScale = 0; | ||
public boolean clickedVisualize = false; | ||
public int bookGuiScale; | ||
public boolean clickedVisualize; | ||
|
||
Map<String, PersistentData.BookData> bookData = new HashMap<>(); | ||
private final Map<ResourceLocation, PersistentData.BookData> bookData = new HashMap<>(); | ||
|
||
public PersistentData.BookData getBookData(Book book) { | ||
String res = book.id.toString(); | ||
if (!bookData.containsKey(res)) { | ||
bookData.put(res, new PersistentData.BookData()); | ||
public DataHolder(JsonObject root) { | ||
this.bookGuiScale = GsonHelper.getAsInt(root, "bookGuiScale", 0); | ||
this.clickedVisualize = GsonHelper.getAsBoolean(root, "clickedVisualize", false); | ||
var obj = GsonHelper.getAsJsonObject(root, "bookData", new JsonObject()); | ||
|
||
for (var e : obj.entrySet()) { | ||
this.bookData.put(new ResourceLocation(e.getKey()), new BookData(e.getValue().getAsJsonObject())); | ||
} | ||
} | ||
|
||
return bookData.get(res); | ||
public PersistentData.BookData getBookData(Book book) { | ||
return bookData.computeIfAbsent(book.id, k -> new BookData(new JsonObject())); | ||
} | ||
|
||
public JsonObject serialize() { | ||
var ret = new JsonObject(); | ||
ret.addProperty("bookGuiScale", this.bookGuiScale); | ||
ret.addProperty("clickedVisualize", this.clickedVisualize); | ||
|
||
var books = new JsonObject(); | ||
for (var e : bookData.entrySet()) { | ||
books.add(e.getKey().toString(), e.getValue().serialize()); | ||
} | ||
ret.add("bookData", books); | ||
return ret; | ||
} | ||
} | ||
|
||
public static final class Bookmark { | ||
public String entry; | ||
// Serialized as page for legacy reasons | ||
@SerializedName("page") public int spread; | ||
public final ResourceLocation entry; | ||
public final int spread; | ||
|
||
public Bookmark(String entry, int spread) { | ||
public Bookmark(ResourceLocation entry, int spread) { | ||
this.entry = entry; | ||
this.spread = spread; | ||
} | ||
|
||
public Bookmark(JsonObject root) { | ||
this.entry = new ResourceLocation(GsonHelper.getAsString(root, "entry")); | ||
this.spread = GsonHelper.getAsInt(root, "page"); // Serialized as page for legacy reasons | ||
} | ||
|
||
public BookEntry getEntry(Book book) { | ||
ResourceLocation res = new ResourceLocation(entry); | ||
return book.getContents().entries.get(res); | ||
return book.getContents().entries.get(entry); | ||
} | ||
|
||
public JsonObject serialize() { | ||
var ret = new JsonObject(); | ||
ret.addProperty("entry", this.entry.toString()); | ||
ret.addProperty("page", this.spread); // Serialized as page for legacy reasons | ||
return ret; | ||
} | ||
} | ||
|
||
public static final class BookData { | ||
public List<String> viewedEntries = new ArrayList<>(); | ||
public List<Bookmark> bookmarks = new ArrayList<>(); | ||
public List<String> history = new ArrayList<>(); | ||
public List<String> completedManualQuests = new ArrayList<>(); | ||
public final List<ResourceLocation> viewedEntries = new ArrayList<>(); | ||
public final List<Bookmark> bookmarks = new ArrayList<>(); | ||
public final List<ResourceLocation> history = new ArrayList<>(); | ||
public final List<ResourceLocation> completedManualQuests = new ArrayList<>(); | ||
|
||
public BookData(JsonObject root) { | ||
var emptyArray = new JsonArray(); | ||
for (var e : GsonHelper.getAsJsonArray(root, "viewedEntries", emptyArray)) { | ||
viewedEntries.add(new ResourceLocation(e.getAsString())); | ||
} | ||
for (var e : GsonHelper.getAsJsonArray(root, "bookmarks", emptyArray)) { | ||
bookmarks.add(new Bookmark(e.getAsJsonObject())); | ||
} | ||
for (var e : GsonHelper.getAsJsonArray(root, "history", emptyArray)) { | ||
history.add(new ResourceLocation(e.getAsString())); | ||
} | ||
for (var e : GsonHelper.getAsJsonArray(root, "completedManualQuests", emptyArray)) { | ||
completedManualQuests.add(new ResourceLocation(e.getAsString())); | ||
} | ||
} | ||
|
||
public JsonObject serialize() { | ||
var ret = new JsonObject(); | ||
var viewed = new JsonArray(); | ||
this.viewedEntries.stream().map(Object::toString).forEach(viewed::add); | ||
ret.add("viewedEntries", viewed); | ||
|
||
var bookmarks = new JsonArray(); | ||
this.bookmarks.stream().map(Bookmark::serialize).forEach(bookmarks::add); | ||
ret.add("bookmarks", bookmarks); | ||
|
||
var completed = new JsonArray(); | ||
this.completedManualQuests.stream().map(Object::toString).forEach(completed::add); | ||
ret.add("completedManualQuests", completed); | ||
|
||
return ret; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters