From 54e236158db9b5947d125f83b29e53cf27f73a79 Mon Sep 17 00:00:00 2001
From: DeDiamondPro <67508414+DeDiamondPro@users.noreply.github.com>
Date: Thu, 19 Oct 2023 23:32:12 +0200
Subject: Use atomic move for config + small cleanup (#881)
---
.../notenoughupdates/NotEnoughUpdates.java | 58 ++--------
.../notenoughupdates/core/config/ConfigUtil.java | 119 +++++++++++++++++++++
.../notenoughupdates/miscfeatures/FairySouls.java | 21 +---
.../miscfeatures/ItemCustomizeManager.java | 31 +-----
.../miscfeatures/PetInfoOverlay.java | 30 +-----
.../notenoughupdates/miscfeatures/SlotLocking.java | 41 ++-----
.../miscfeatures/StorageManager.java | 34 +-----
7 files changed, 146 insertions(+), 188 deletions(-)
create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/core/config/ConfigUtil.java
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
index 268fddd5..f878dbf1 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
@@ -26,6 +26,7 @@ import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.autosubscribe.AutoLoad;
import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe;
import io.github.moulberry.notenoughupdates.core.BackgroundBlur;
+import io.github.moulberry.notenoughupdates.core.config.ConfigUtil;
import io.github.moulberry.notenoughupdates.cosmetics.ShaderManager;
import io.github.moulberry.notenoughupdates.listener.ChatListener;
import io.github.moulberry.notenoughupdates.listener.ItemTooltipEssenceShopListener;
@@ -83,14 +84,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.awt.*;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Set;
@@ -205,16 +199,7 @@ public class NotEnoughUpdates {
configFile = new File(neuDir, "configNew.json");
if (configFile.exists()) {
- try (
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- new FileInputStream(configFile),
- StandardCharsets.UTF_8
- ))
- ) {
- config = gson.fromJson(reader, NEUConfig.class);
- } catch (Exception exc) {
- new RuntimeException("Invalid config file. This will reset the config to default", exc).printStackTrace();
- }
+ config = ConfigUtil.loadConfig(NEUConfig.class, configFile, gson);
}
ItemCustomizeManager.loadCustomization(new File(neuDir, "itemCustomization.json"));
@@ -326,40 +311,13 @@ public class NotEnoughUpdates {
} catch (Exception ignored) {
}
- try {
- configFile.createNewFile();
-
- try (
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
- new FileOutputStream(configFile),
- StandardCharsets.UTF_8
- ))
- ) {
- writer.write(gson.toJson(config));
- }
- } catch (Exception ignored) {
- }
+ ConfigUtil.saveConfig(config, configFile, gson);
- try {
- ItemCustomizeManager.saveCustomization(new File(neuDir, "itemCustomization.json"));
- } catch (Exception ignored) {
- }
- try {
- StorageManager.getInstance().saveConfig(new File(neuDir, "storageItems.json"));
- } catch (Exception ignored) {
- }
- try {
- FairySouls.getInstance().saveFoundSoulsForAllProfiles(new File(neuDir, "collected_fairy_souls.json"), gson);
- } catch (Exception ignored) {
- }
- try {
- PetInfoOverlay.saveConfig(new File(neuDir, "petCache.json"));
- } catch (Exception ignored) {
- }
- try {
- SlotLocking.getInstance().saveConfig(new File(neuDir, "slotLocking.json"));
- } catch (Exception ignored) {
- }
+ ItemCustomizeManager.saveCustomization(new File(neuDir, "itemCustomization.json"));
+ StorageManager.getInstance().saveConfig(new File(neuDir, "storageItems.json"));
+ FairySouls.getInstance().saveFoundSoulsForAllProfiles(new File(neuDir, "collected_fairy_souls.json"), gson);
+ PetInfoOverlay.saveConfig(new File(neuDir, "petCache.json"));
+ SlotLocking.getInstance().saveConfig(new File(neuDir, "slotLocking.json"));
}
/**
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/ConfigUtil.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/ConfigUtil.java
new file mode 100644
index 00000000..e6fb8799
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/ConfigUtil.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2023 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see .
+ */
+
+package io.github.moulberry.notenoughupdates.core.config;
+
+import com.google.gson.Gson;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+public class ConfigUtil {
+ public static @Nullable T loadConfig(Class configClass, File file, Gson gson) {
+ return loadConfig(configClass, file, gson, false);
+ }
+
+ public static @Nullable T loadConfig(Class configClass, File file, Gson gson, boolean useGzip) {
+ return loadConfig(configClass, file, gson, useGzip, true);
+ }
+
+ public static @Nullable T loadConfig(
+ Class configClass,
+ File file,
+ Gson gson,
+ boolean useGzip,
+ boolean handleError
+ ) {
+ if (!file.exists()) return null;
+ try (
+ BufferedReader reader = useGzip ?
+ new BufferedReader(new InputStreamReader(
+ new GZIPInputStream(Files.newInputStream(file.toPath())),
+ StandardCharsets.UTF_8
+ )) :
+ new BufferedReader(new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8))
+ ) {
+ return gson.fromJson(reader, configClass);
+ } catch (Exception e) {
+ if (!handleError) return null;
+ new RuntimeException(
+ "Invalid config file '" + file + "'. This will reset the config to default",
+ e
+ ).printStackTrace();
+ try {
+ // Try to save a version of the corrupted config for debugging purposes
+ Files.copy(
+ file.toPath(),
+ new File(file.getParent(), file.getName() + ".corrupted").toPath(),
+ StandardCopyOption.REPLACE_EXISTING
+ );
+ } catch (Exception ignored) {
+ }
+ }
+ return null;
+ }
+
+ public static void saveConfig(Object config, File file, Gson gson) {
+ saveConfig(config, file, gson, false);
+ }
+
+ public static void saveConfig(Object config, File file, Gson gson, boolean useGzip) {
+ File tempFile = new File(file.getParent(), file.getName() + ".temp");
+ try {
+ tempFile.createNewFile();
+ try (
+ BufferedWriter writer = useGzip ?
+ new BufferedWriter(new OutputStreamWriter(
+ new GZIPOutputStream(Files.newOutputStream(tempFile.toPath())),
+ StandardCharsets.UTF_8
+ )) :
+ new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(tempFile.toPath()), StandardCharsets.UTF_8))
+ ) {
+ writer.write(gson.toJson(config));
+ }
+
+ if (loadConfig(config.getClass(), tempFile, gson, useGzip, false) == null) {
+ System.out.println("Config verification failed for " + tempFile + ", could not save config properly.");
+ tempFile.delete();
+ return;
+ }
+
+ try {
+ Files.move(tempFile.toPath(), file.toPath(), StandardCopyOption.ATOMIC_MOVE);
+ } catch (IOException e) {
+ // If atomic move fails it could be because it isn't supported or because the implementation of it
+ // doesn't overwrite the old file, in this case we will try a normal move.
+ Files.move(tempFile.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ tempFile.delete();
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java
index 97aa25d4..a1bf34a3 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java
@@ -26,6 +26,7 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe;
+import io.github.moulberry.notenoughupdates.core.config.ConfigUtil;
import io.github.moulberry.notenoughupdates.core.util.StringUtils;
import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
import io.github.moulberry.notenoughupdates.util.Constants;
@@ -42,14 +43,10 @@ import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -349,21 +346,7 @@ public class FairySouls {
}
public void saveFoundSoulsForAllProfiles(File file, Gson gson) {
- try {
- //noinspection ResultOfMethodCallIgnored
- file.createNewFile();
-
- try (
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
- new FileOutputStream(file),
- StandardCharsets.UTF_8
- ))
- ) {
- writer.write(gson.toJson(allProfilesFoundSouls));
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
+ ConfigUtil.saveConfig(allProfilesFoundSouls, file, gson);
}
public void tick() {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java
index ece2f61c..afb63dff 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java
@@ -24,6 +24,7 @@ import com.google.gson.GsonBuilder;
import io.github.moulberry.notenoughupdates.NEUManager;
import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe;
import io.github.moulberry.notenoughupdates.core.ChromaColour;
+import io.github.moulberry.notenoughupdates.core.config.ConfigUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.layers.LayerArmorBase;
@@ -45,14 +46,7 @@ import org.lwjgl.opengl.GL14;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
@@ -298,33 +292,14 @@ public class ItemCustomizeManager {
}
public static void loadCustomization(File file) {
- try (
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- new FileInputStream(file),
- StandardCharsets.UTF_8
- ))
- ) {
- itemDataMap = GSON.fromJson(reader, ItemDataMap.class);
- } catch (Exception ignored) {
- }
+ itemDataMap = ConfigUtil.loadConfig(ItemDataMap.class, file, GSON);
if (itemDataMap == null) {
itemDataMap = new ItemDataMap();
}
}
public static void saveCustomization(File file) {
- try {
- file.createNewFile();
- try (
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
- new FileOutputStream(file),
- StandardCharsets.UTF_8
- ))
- ) {
- writer.write(GSON.toJson(itemDataMap));
- }
- } catch (Exception ignored) {
- }
+ ConfigUtil.saveConfig(itemDataMap, file, GSON);
}
public static Item getCustomItem(ItemStack stack) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
index 6c0e2499..b24af575 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
@@ -26,6 +26,7 @@ import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.config.ConfigUtil;
import io.github.moulberry.notenoughupdates.core.config.Position;
import io.github.moulberry.notenoughupdates.core.util.StringUtils;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils;
@@ -55,13 +56,7 @@ import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.apache.commons.lang3.text.WordUtils;
import org.lwjgl.util.vector.Vector2f;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.File;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
@@ -169,33 +164,14 @@ public class PetInfoOverlay extends TextOverlay {
private int xpAddTimer = 0;
public static void loadConfig(File file) {
- try (
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- Files.newInputStream(file.toPath()),
- StandardCharsets.UTF_8
- ))
- ) {
- config = GSON.fromJson(reader, PetConfig.class);
- } catch (Exception ignored) {
- }
+ config = ConfigUtil.loadConfig(PetConfig.class, file, GSON);
if (config == null) {
config = new PetConfig();
}
}
public static void saveConfig(File file) {
- try {
- file.createNewFile();
- try (
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
- Files.newOutputStream(file.toPath()),
- StandardCharsets.UTF_8
- ))
- ) {
- writer.write(GSON.toJson(config));
- }
- } catch (Exception ignored) {
- }
+ ConfigUtil.saveConfig(config, file, GSON);
}
public static void clearPet() {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java
index c8ac39b2..72aeaa23 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java
@@ -23,6 +23,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe;
+import io.github.moulberry.notenoughupdates.core.config.ConfigUtil;
import io.github.moulberry.notenoughupdates.core.config.KeybindHelper;
import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent;
@@ -55,14 +56,7 @@ import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Vector2f;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
import java.util.HashMap;
@NEUAutoSubscribe
@@ -113,15 +107,7 @@ public class SlotLocking {
public Slot getRealSlot() {return realSlot;}
public void loadConfig(File file) {
- try (
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- new FileInputStream(file),
- StandardCharsets.UTF_8
- ))
- ) {
- config = GSON.fromJson(reader, SlotLockingConfig.class);
- } catch (Exception ignored) {
- }
+ config = ConfigUtil.loadConfig(SlotLockingConfig.class, file, GSON);
if (config == null) {
config = new SlotLockingConfig();
}
@@ -163,19 +149,7 @@ public class SlotLocking {
private final long[] slotChanges = new long[9];
public void saveConfig(File file) {
- try {
- file.createNewFile();
- try (
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
- new FileOutputStream(file),
- StandardCharsets.UTF_8
- ))
- ) {
- writer.write(GSON.toJson(config));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
+ ConfigUtil.saveConfig(config, file, GSON);
}
private LockedSlot[] getDataForProfile() {
@@ -191,12 +165,10 @@ public class SlotLocking {
k -> new SlotLockProfile()
);
-
if (profile.slotLockData[0] == null) {
profile.slotLockData[0] = new SlotLockData();
}
-
if (!"rift".equals(SBInfo.getInstance().getLocation())) {
return profile.slotLockData[0].lockedSlots;
} else {
@@ -209,7 +181,6 @@ public class SlotLocking {
return DEFAULT_LOCKED_SLOT;
}
-
LockedSlot slot = lockedSlots[index];
if (slot == null) {
@@ -747,10 +718,14 @@ public class SlotLocking {
}
boolean setTopHalfBarrier = false;
+
@SubscribeEvent
public void barrierInventory(ReplaceItemEvent event) {
if (event.getSlotNumber() < 9 ||
- (pairingSlot != null && (event.getSlotNumber() == pairingSlot.slotNumber || isArmourSlot(event.getSlotNumber(), pairingSlot.slotNumber))) ||
+ (pairingSlot != null && (event.getSlotNumber() == pairingSlot.slotNumber || isArmourSlot(
+ event.getSlotNumber(),
+ pairingSlot.slotNumber
+ ))) ||
!setTopHalfBarrier ||
!(event.getInventory() instanceof InventoryPlayer)) return;
ItemStack stack = new ItemStack(Blocks.barrier);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StorageManager.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StorageManager.java
index e2ede605..985ed11a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StorageManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StorageManager.java
@@ -31,6 +31,7 @@ import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.config.ConfigUtil;
import io.github.moulberry.notenoughupdates.miscgui.StorageOverlay;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import io.github.moulberry.notenoughupdates.util.Utils;
@@ -62,22 +63,13 @@ import net.minecraft.network.play.server.S2EPacketCloseWindow;
import net.minecraft.network.play.server.S2FPacketSetSlot;
import net.minecraft.network.play.server.S30PacketWindowItems;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
import java.lang.reflect.Type;
-import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
public class StorageManager {
private static final StorageManager INSTANCE = new StorageManager();
@@ -298,34 +290,14 @@ public class StorageManager {
private static final Pattern ECHEST_WINDOW_REGEX = Pattern.compile("Ender Chest \\((\\d+)/(\\d+)\\)");
public void loadConfig(File file) {
- try (
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- new GZIPInputStream(new FileInputStream(file)),
- StandardCharsets.UTF_8
- ))
- ) {
- storageConfig = GSON.fromJson(reader, StorageConfig.class);
- } catch (Exception ignored) {
- }
+ storageConfig = ConfigUtil.loadConfig(StorageConfig.class, file, GSON, true);
if (storageConfig == null) {
storageConfig = new StorageConfig();
}
}
public void saveConfig(File file) {
- try {
- file.createNewFile();
- try (
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
- new GZIPOutputStream(new FileOutputStream(file)),
- StandardCharsets.UTF_8
- ))
- ) {
- writer.write(GSON.toJson(storageConfig));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
+ ConfigUtil.saveConfig(storageConfig, file, GSON, true);
}
public ItemStack getMissingBackpackStack(int storageId) {
--
cgit