Respackopts/src/main/java/io/gitlab/jfronny/respackopts/Respackopts.java

159 lines
6.8 KiB
Java

package io.gitlab.jfronny.respackopts;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.gitlab.jfronny.respackopts.filters.DirFilterEventImpl;
import io.gitlab.jfronny.respackopts.filters.FileFilterEventImpl;
import io.gitlab.jfronny.respackopts.gson.*;
import io.gitlab.jfronny.respackopts.gson.entry.BooleanEntrySerializer;
import io.gitlab.jfronny.respackopts.gson.entry.ConfigBranchSerializer;
import io.gitlab.jfronny.respackopts.gson.entry.EnumEntrySerializer;
import io.gitlab.jfronny.respackopts.gson.entry.NumericEntrySerializer;
import io.gitlab.jfronny.respackopts.integration.FrexCompat;
import io.gitlab.jfronny.respackopts.model.ConfigFile;
import io.gitlab.jfronny.respackopts.model.DirRpo;
import io.gitlab.jfronny.respackopts.model.FileRpo;
import io.gitlab.jfronny.respackopts.model.condition.Condition;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBooleanEntry;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch;
import io.gitlab.jfronny.respackopts.model.tree.ConfigEnumEntry;
import io.gitlab.jfronny.respackopts.model.tree.ConfigNumericEntry;
import io.gitlab.jfronny.respackopts.util.GuiFactory;
import io.gitlab.jfronny.respackopts.util.MetaCache;
import io.gitlab.jfronny.respackopts.util.RpoCommand;
import meteordevelopment.starscript.Script;
import meteordevelopment.starscript.StandardLib;
import meteordevelopment.starscript.Starscript;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.impl.gui.FabricGuiEntry;
import net.minecraft.client.MinecraftClient;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@Environment(EnvType.CLIENT)
public class Respackopts implements ClientModInitializer {
public static final Integer META_VERSION = 6;
public static final String FILE_EXTENSION = ".rpo";
public static final Gson GSON;
public static Starscript STAR_SCRIPT;
public static final String ID = "respackopts";
public static final Logger LOGGER = LogManager.getFormatterLogger(ID);
public static final Identifier CONF_ID = new Identifier(ID, "conf.json");
public static final Set<Runnable> SAVE_ACTIONS = new HashSet<>();
public static final GuiFactory GUI_FACTORY = new GuiFactory();
public static boolean forcePackReload = false;
public static Path FALLBACK_CONF_DIR;
public static ConfigFile CONFIG;
public static final Identifier RPO_SHADER_ID = new Identifier(Respackopts.ID, "config_supplier");
private static String shaderImportSource;
static {
GSON = new GsonBuilder()
.registerTypeAdapter(ConfigEnumEntry.class, new EnumEntrySerializer())
.registerTypeAdapter(ConfigNumericEntry.class, new NumericEntrySerializer())
.registerTypeAdapter(ConfigBooleanEntry.class, new BooleanEntrySerializer())
.registerTypeAdapter(ConfigBranch.class, new ConfigBranchSerializer())
.registerTypeAdapter(Script.class, new ScriptDeserializer())
.registerTypeAdapter(FileRpo.class, new FileRpoDeserializer())
.registerTypeAdapter(DirRpo.class, new DirRpoDeserializer())
.registerTypeAdapter(Condition.class, new ConditionDeserializer())
.registerTypeAdapterFactory(new SingleEntrySetTypeAdapterFactory())
.registerTypeAdapterFactory(new SingleEntryListTypeAdapterFactory())
.setPrettyPrinting()
.create();
try {
FALLBACK_CONF_DIR = FabricLoader.getInstance().getConfigDir().resolve(ID);
CONFIG = ConfigFile.load();
} catch (Throwable e) {
LOGGER.error("Could not resolve config directory", e);
}
try {
STAR_SCRIPT = new Starscript();
} catch (Exception e) {
FabricGuiEntry.displayCriticalError(new Exception("Respackopts could not initialize Starscript. Expect issues with packs that use it", e), false);
}
StandardLib.init(STAR_SCRIPT);
}
@Override
public void onInitializeClient() {
try {
Files.createDirectories(FALLBACK_CONF_DIR);
} catch (IOException e) {
LOGGER.error("Could not initialize config directory", e);
}
if (CONFIG.debugLogs)
SAVE_ACTIONS.add(() -> LOGGER.info("Save"));
SAVE_ACTIONS.add(() -> {
MetaCache.forEach((id, branch) -> STAR_SCRIPT.set(sanitizeString(id), branch::buildStarscript));
});
SAVE_ACTIONS.add(() -> {
if (CONFIG.debugLogs)
LOGGER.info("Generating shader code");
StringBuilder sb = new StringBuilder();
sb.append("#ifndef respackopts_loaded");
sb.append("\n#define respackopts_loaded");
MetaCache.forEach((id, branch) -> branch.buildShader(sb, sanitizeString(id)));
sb.append("\n#endif");
shaderImportSource = sb.toString();
});
DirFilterEventImpl.init();
FileFilterEventImpl.init();
if (CONFIG.debugCommands)
RpoCommand.register();
if (FabricLoader.getInstance().isModLoaded("frex")) {
FrexCompat.onInitializeFrex();
}
}
public static String sanitizeString(String s) {
// This trims whitespace/underscores and removes non-alphabetical or underscore characters
// ^ = start of string
// $ = end of string
// * = zero or more times
// [\\s_] = whitespace or underscores
// | = or
// [^a-zA-Z_] = not character or underscore
return s.replaceAll("[^a-zA-Z_]|^[\\s_]*|[\\s_]*$", "");
}
public static CompletableFuture<Void> forceReloadResources() {
if (CONFIG.debugLogs)
LOGGER.info("Forcing resource reload");
return CompletableFuture.allOf(MinecraftClient.getInstance().reloadResources(),
reloadData());
}
public static CompletableFuture<Void> reloadData() {
IntegratedServer is = MinecraftClient.getInstance().getServer();
if (is != null) {
is.getDataPackManager().scanPacks();
return is.reloadResources(is.getDataPackManager().getEnabledNames());
}
return CompletableFuture.completedFuture(null);
}
public static String getShaderImportSource() {
if (shaderImportSource == null) {
Respackopts.LOGGER.error("Shader import source is null");
return "";
}
return shaderImportSource;
}
}