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