Skip to content

Commit

Permalink
move to gzip nbt
Browse files Browse the repository at this point in the history
  • Loading branch information
TechLord22 committed Mar 28, 2024
1 parent 2a44a06 commit 7a7aca2
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 43 deletions.
102 changes: 77 additions & 25 deletions src/main/java/gregtech/api/persistence/PersistentData.java
Original file line number Diff line number Diff line change
@@ -1,56 +1,108 @@
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;
}

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);
}
}
}
27 changes: 9 additions & 18 deletions src/main/java/gregtech/api/recipes/GTRecipeInputCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -35,9 +35,6 @@ public final class GTRecipeInputCache {
private static ObjectOpenHashSet<GTRecipeInput> 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() {}

Expand Down Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -146,8 +138,7 @@ public static List<GTRecipeInput> deduplicateInputs(List<GTRecipeInput> 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));
Expand Down

0 comments on commit 7a7aca2

Please sign in to comment.