diff --git a/src/main/java/gregtech/api/persistence/PersistentData.java b/src/main/java/gregtech/api/persistence/PersistentData.java index d1fa1ed9b9b..dc88872d9a3 100644 --- a/src/main/java/gregtech/api/persistence/PersistentData.java +++ b/src/main/java/gregtech/api/persistence/PersistentData.java @@ -1,25 +1,28 @@ package gregtech.api.persistence; import gregtech.api.GTValues; +import gregtech.api.util.GTLog; -import net.minecraftforge.common.config.Configuration; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fml.common.Loader; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; import java.nio.file.Path; public final class PersistentData { - public static final String CATEGORY_NAME = "persistent data"; - private static final PersistentData INSTANCE = new PersistentData(); - private static final String FILE_NAME = "persistent_data.cfg"; - private @Nullable Configuration config; + private @Nullable Path path; + private @Nullable NBTTagCompound tag; public static @NotNull PersistentData instance() { return INSTANCE; @@ -27,30 +30,79 @@ public final class PersistentData { private PersistentData() {} + @ApiStatus.Internal + public void init() { + this.path = Loader.instance().getConfigDir().toPath() + .resolve(GTValues.MODID) + .resolve("persistent_data.dat"); + } + /** - * @return the persistent data storage + * @return the stored persistent data */ - public @NotNull Configuration getConfig() { - if (config == null) { - Path configFolderPath = Loader.instance().getConfigDir().toPath().resolve(GTValues.MODID); - File file = configFolderPath.resolve(FILE_NAME).toFile(); - config = new Configuration(file); + public synchronized @NotNull NBTTagCompound getTag() { + if (this.tag == null) { + this.tag = read(); } - return config; + return this.tag; } - @ApiStatus.Internal - public void init() { - Configuration configuration = getConfig(); - configuration.load(); - String comment = """ - GregTech Persistent Data. Items in this file will persist across game loads. - Modifications to this file may be overwritten by GT. - If you are a modpack author, you should ship this file in releases."""; - configuration.addCustomCategoryComment(CATEGORY_NAME, comment); - - if (configuration.hasChanged()) { - configuration.save(); + /** + * @return the read NBTTagCompound from disk + */ + private @NotNull NBTTagCompound read() { + GTLog.logger.debug("Reading persistent data from path {}", path); + if (this.path == null) { + throw new IllegalStateException("Persistent data path cannot be null"); + } + + if (!Files.exists(path)) { + return new NBTTagCompound(); + } + + try (InputStream inputStream = Files.newInputStream(this.path)) { + return CompressedStreamTools.readCompressed(inputStream); + } catch (IOException e) { + GTLog.logger.error("Failed to read persistent data", e); + return new NBTTagCompound(); + } + } + + /** + * Save the GT Persistent data to disk + */ + public synchronized void save() { + if (this.tag != null) { + write(this.tag); + } + } + + /** + * @param tagCompound the tag compound to save to disk + */ + private void write(@NotNull NBTTagCompound tagCompound) { + GTLog.logger.debug("Writing persistent data to path {}", path); + if (tagCompound.isEmpty()) { + return; + } + + if (this.path == null) { + throw new IllegalStateException("Persistent data path cannot be null"); + } + + if (!Files.exists(path)) { + try { + Files.createDirectories(path.getParent()); + } catch (IOException e) { + GTLog.logger.error("Could not create persistent data dir", e); + return; + } + } + + try (OutputStream outputStream = Files.newOutputStream(path)) { + CompressedStreamTools.writeCompressed(tagCompound, outputStream); + } catch (IOException e) { + GTLog.logger.error("Failed to write persistent data", e); } } } diff --git a/src/main/java/gregtech/api/recipes/GTRecipeInputCache.java b/src/main/java/gregtech/api/recipes/GTRecipeInputCache.java index 5e63b6fd4da..4e9a68fdf03 100644 --- a/src/main/java/gregtech/api/recipes/GTRecipeInputCache.java +++ b/src/main/java/gregtech/api/recipes/GTRecipeInputCache.java @@ -6,8 +6,8 @@ import gregtech.api.util.GTLog; import gregtech.common.ConfigHolder; -import net.minecraftforge.common.config.Configuration; -import net.minecraftforge.common.config.Property; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.MathHelper; import it.unimi.dsi.fastutil.Hash; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; @@ -35,9 +35,6 @@ public final class GTRecipeInputCache { private static ObjectOpenHashSet instances; private static final String DATA_NAME = "expectedIngredientInstances"; - private static final String DATA_COMMENT = """ - The expected amount of unique GT recipe ingredients. - This setting improves memory allocation and garbage collection during game-load."""; private GTRecipeInputCache() {} @@ -67,22 +64,17 @@ public static void disableCache() { instances = null; if (size >= MINIMUM_CACHE_SIZE && size < MAXIMUM_CACHE_SIZE) { - Configuration config = PersistentData.instance().getConfig(); - Property expected = getExpectedInstanceAmount(config); - - if (expected.getInt() != size) { - expected.set(size); - if (expected.hasChanged()) { - config.save(); - } + NBTTagCompound tagCompound = PersistentData.instance().getTag(); + if (getExpectedInstanceAmount(tagCompound) != size) { + tagCompound.setInteger(DATA_NAME, size); + PersistentData.instance().save(); } } } } - private static @NotNull Property getExpectedInstanceAmount(@NotNull Configuration configuration) { - return configuration.get(PersistentData.CATEGORY_NAME, DATA_NAME, MINIMUM_CACHE_SIZE, - DATA_COMMENT, MINIMUM_CACHE_SIZE, MAXIMUM_CACHE_SIZE); + private static int getExpectedInstanceAmount(@NotNull NBTTagCompound tagCompound) { + return MathHelper.clamp(tagCompound.getInteger(DATA_NAME), MINIMUM_CACHE_SIZE, MAXIMUM_CACHE_SIZE); } /** @@ -146,8 +138,7 @@ public static List deduplicateInputs(List inputs) * @return the optimal expected input cache size */ private static int calculateOptimalExpectedSize() { - int min = getExpectedInstanceAmount(PersistentData.instance().getConfig()) - .getInt(MINIMUM_CACHE_SIZE); + int min = Math.max(getExpectedInstanceAmount(PersistentData.instance().getTag()), MINIMUM_CACHE_SIZE); for (int i = 13; i < 31; i++) { int sizeToTest = 1 << i; int arraySize = nextHighestPowerOf2((int) (sizeToTest / Hash.DEFAULT_LOAD_FACTOR));