Update for 1.19.1 with split sources

This commit is contained in:
Johannes Frohnmeyer 2022-07-28 14:10:59 +02:00
parent 758c2eff68
commit 5fd4fdad94
Signed by: Johannes
GPG Key ID: E76429612C2929F4
36 changed files with 476 additions and 264 deletions

View File

@ -17,13 +17,14 @@ repositories {
}
dependencies {
//TODO move modmenu/frex to client-only once they get remapped
modImplementation("net.fabricmc.fabric-api:fabric-api:${project.fabric_version}")
modImplementation("com.terraformersmc:modmenu:4.0.0-beta.4")
modCompileOnly(modRuntimeOnly("com.terraformersmc:modmenu:4.0.5"))
include modImplementation("io.gitlab.jfronny:muscript:${project.muscript_version}")
modApi("me.shedaniel.cloth:cloth-config-fabric:7.0.65") {
modApi("me.shedaniel.cloth:cloth-config-fabric:7.0.73") {
exclude(group: "net.fabricmc.fabric-api")
}
modCompileOnly "io.vram:frex-fabric-mc119:+"
modCompileOnly("io.vram:frex-fabric-mc119:+")
modImplementation("io.gitlab.jfronny.libjf:libjf-data-manipulation-v0:${project.jfapi_version}")
modRuntimeOnly("io.gitlab.jfronny.libjf:libjf-devutil-v0:${project.jfapi_version}")
@ -35,7 +36,7 @@ dependencies {
// }
// DashLoader "compatibility"
// modRuntimeOnly 'dev.quantumfusion.dashloader:dashloader-definitions:3.0-rc14-1.18'
// clientRuntimeOnly("dev.quantumfusion.dashloader:dashloader-definitions:3.0-rc14-1.18")
}
test {

View File

@ -8,12 +8,12 @@ Respackopts stores configurations next to their corresponding resource packs (`s
This file contains all applied config options as saved by respackopts.
## Dump the internal representation
Running `/rpo dump config` will dump all data available about the enabled packs, including their config options (but not individual configurations like .rpo files)
Running `/rpoc dump config` will dump all data available about the enabled packs, including their config options (but not individual configurations like .rpo files)
You can use this if a conf.json isn't working as expected
## Dump GLSL code
You can run the command `/rpo dump glsl` to dump the shader code generated by respackopts to a file.
You can run the command `/rpoc dump glsl` to dump the shader code generated by respackopts to a file.
I recommend reading through it if your shader is misbehaving.
The content imported to your shader by the integrations will equal the dumped code.

View File

@ -23,5 +23,5 @@ You will then need to include this file in the places you want to access its val
## Using the values
All values respackotps exposes follow the form: `<id>_<entry>` or `<id>_<category>_<entry>`
To view the code respackotps generates for your pack, you can run the `/rpo dump glsl` command in minecraft (You must enable the `debugCommands` config option for this).
To view the code respackotps generates for your pack, you can run the `/rpoc dump glsl` command in minecraft (You must enable the `debugCommands` config option for this).
This will create a frex.frag file in your .minecraft/respackotps directory containing the generated shader code (available since 2.7.0).

View File

@ -1,12 +1,12 @@
# https://fabricmc.net/develop/
minecraft_version=1.19
yarn_mappings=build.2
loader_version=0.14.7
minecraft_version=1.19.1
yarn_mappings=build.1
loader_version=0.14.8
maven_group=io.gitlab.jfronny
archives_base_name=respackopts
fabric_version=0.55.3+1.19
jfapi_version=2.9.1
muscript_version=2022.6.13+11-33-14
fabric_version=0.58.5+1.19.1
jfapi_version=2.10.0
muscript_version=2022.7.4+11-13-3
modrinth_id=respackopts
modrinth_required_dependencies=fabric-api, cloth-config, libjf

View File

@ -0,0 +1,84 @@
package io.gitlab.jfronny.respackopts;
import io.gitlab.jfronny.respackopts.integration.*;
import io.gitlab.jfronny.respackopts.util.GuiFactory;
import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.fabricmc.api.*;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.Identifier;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Environment(EnvType.CLIENT)
public class RespackoptsClient implements ClientModInitializer, SaveHook {
private static final boolean FREX_LOADED = FabricLoader.getInstance().isModLoaded("frex");
public static final GuiFactory GUI_FACTORY = new GuiFactory();
public static final Identifier RPO_SHADER_ID = new Identifier(Respackopts.ID, "config_supplier");
public static boolean forcePackReload = false;
private static String shaderImportSource;
public static String getShaderImportSource() {
if (shaderImportSource == null) {
Respackopts.LOGGER.error("Shader import source is null");
return "";
}
return shaderImportSource;
}
@Override
public void onInitializeClient() {
if (Respackopts.CONFIG.debugCommands)
RpoClientCommand.register();
if (FREX_LOADED) {
FrexCompat.init();
}
}
@Override
public CompletableFuture<Void> onSave(Arguments args) {
if (Respackopts.CONFIG.debugLogs)
Respackopts.LOGGER.info("Generating shader code");
StringBuilder sb = new StringBuilder();
sb.append("#ifndef respackopts_loaded");
sb.append("\n#define respackopts_loaded");
MetaCache.forEach((key, state) -> state.configBranch().buildShader(sb, Respackopts.sanitizeString(state.packId())));
sb.append("\n#endif");
RespackoptsClient.shaderImportSource = sb.toString();
if (FREX_LOADED) {
FrexCompat.handleSave();
}
if (args.flagResourcesForReload()) {
forcePackReload = true;
DashLoaderCompat.requestForceReload();
}
List<CompletableFuture<Void>> futures = new ArrayList<>();
if (args.reloadResourcesImmediately()) {
futures.add(forceReloadResources());
}
if (args.reloadData()) {
futures.add(reloadIntegratedServerData());
}
return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new));
}
public static CompletableFuture<Void> forceReloadResources() {
forcePackReload = true;
DashLoaderCompat.requestForceReload();
if (Respackopts.CONFIG.debugLogs) Respackopts.LOGGER.info("Forcing resource reload");
return CompletableFuture.allOf(MinecraftClient.getInstance().reloadResources());
}
public static CompletableFuture<Void> reloadIntegratedServerData() {
IntegratedServer is = MinecraftClient.getInstance().getServer();
if (is != null) {
is.getDataPackManager().scanPacks();
return is.reloadResources(is.getDataPackManager().getEnabledNames());
}
return CompletableFuture.completedFuture(null);
}
}

View File

@ -0,0 +1,69 @@
package io.gitlab.jfronny.respackopts;
import com.mojang.brigadier.Command;
import io.gitlab.jfronny.respackopts.integration.SaveHook;
import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.fabricmc.loader.api.*;
import net.minecraft.text.Text;
import java.io.BufferedWriter;
import java.nio.file.*;
import java.util.concurrent.CompletableFuture;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
public class RpoClientCommand {
private static final Version VERSION = FabricLoader.getInstance().getModContainer(Respackopts.ID).get().getMetadata().getVersion();
public static void register() {
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
Command<FabricClientCommandSource> getVersion = ctx -> {
ctx.getSource().sendFeedback(Text.translatable("respackopts.versionText", VERSION, Respackopts.META_VERSION));
return 1;
};
Command<FabricClientCommandSource> dumpConfig = ctx -> {
MetaCache.forEach((id, branch) -> ctx.getSource().sendFeedback(dump(branch.toString(), id + ".txt")));
return 1;
};
Command<FabricClientCommandSource> dumpGlsl = ctx -> {
ctx.getSource().sendFeedback(dump(RespackoptsClient.getShaderImportSource(), "frex.glsl"));
return 1;
};
Command<FabricClientCommandSource> reload = ctx -> {
MetaCache.clear();
CompletableFuture.allOf(RespackoptsClient.forceReloadResources(), RespackoptsClient.reloadIntegratedServerData())
.thenRun(() -> {
ctx.getSource().sendFeedback(Text.translatable("respackopts.reloadSucceeded"));
}).exceptionally(e -> {
Respackopts.LOGGER.error("Could not reload resources", e);
ctx.getSource().sendError(Text.translatable("respackopts.reloadFailed"));
return null;
});
return 1;
};
dispatcher.register(literal("rpoc").executes(getVersion)
.then(literal("dump").executes(dumpConfig)
.then(literal("config").executes(dumpConfig))
.then(literal("glsl").executes(dumpGlsl)))
.then(literal("version").executes(getVersion))
.then(literal("reload").executes(reload)));
});
}
private static final Path dumpPath = FabricLoader.getInstance().getGameDir().resolve("respackopts");
private static Text dump(String text, String fileName) {
try {
if (!Files.exists(dumpPath)) Files.createDirectories(dumpPath);
Path filePath = dumpPath.resolve(fileName);
try (BufferedWriter bw = Files.newBufferedWriter(filePath, StandardOpenOption.CREATE)) {
bw.write(text);
}
return Text.translatable("respackopts.dumpSucceeded", filePath.toAbsolutePath());
}
catch (Throwable e) {
Respackopts.LOGGER.error("Could not dump resource", e);
return Text.translatable("respackopts.dumpFailed");
}
}
}

View File

@ -0,0 +1,19 @@
package io.gitlab.jfronny.respackopts.integration;
import io.gitlab.jfronny.respackopts.*;
import io.vram.frex.api.config.*;
public class FrexCompat {
public static void init() {
ShaderConfig.registerShaderConfigSupplier(RespackoptsClient.RPO_SHADER_ID, RespackoptsClient::getShaderImportSource);
Respackopts.LOGGER.info("enabled frex/canvas support");
}
public static void handleSave() {
try {
ShaderConfig.invalidateShaderConfig();
} catch (RuntimeException e) {
Respackopts.LOGGER.error("Could not reload shader config", e);
}
}
}

View File

@ -2,6 +2,7 @@ package io.gitlab.jfronny.respackopts.integration;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import io.gitlab.jfronny.respackopts.RespackoptsClient;
import io.gitlab.jfronny.respackopts.util.MetaCache;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.ConfigFile;
@ -25,12 +26,7 @@ public class ModMenuCompat implements ModMenuApi {
PackReloadType.Aggregator agg = new PackReloadType.Aggregator();
builder.setSavingRunnable(() -> {
if (Respackopts.CONFIG.debugLogs) Respackopts.LOGGER.info("ModMenuCompat SavingRunnable " + agg.get());
Respackopts.CONFIG.save();
MetaCache.save();
if (agg.get() == PackReloadType.Resource) {
DashLoaderCompat.requestForceReload();
Respackopts.forceReloadResources();
}
MetaCache.save(agg.get() == PackReloadType.Resource ? SaveHook.Arguments.RELOAD_ALL : SaveHook.Arguments.DO_NOTHING);
});
//Respackopts config screen
ConfigFile defaultConfig = new ConfigFile();
@ -57,7 +53,7 @@ public class ModMenuCompat implements ModMenuApi {
//Pack config screens
MetaCache.forEach((key, state) -> {
ConfigCategory config = builder.getOrCreateCategory(Text.translatable((state.metadata().version >= 5 ? "rpo." : "respackopts.title.") + state.packId()));
Respackopts.GUI_FACTORY.buildCategory(state.configBranch(), state.packId(), config::addEntry, agg, entryBuilder, "");
RespackoptsClient.GUI_FACTORY.buildCategory(state.configBranch(), state.packId(), config::addEntry, agg, entryBuilder, "");
});
return builder.build();
}

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.respackopts.mixin;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.RespackoptsClient;
import net.minecraft.client.gl.GLImportProcessor;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -8,9 +8,9 @@ import org.spongepowered.asm.mixin.injection.ModifyArg;
@Mixin(GLImportProcessor.class)
public class GLImportProcessorMixin {
private static final String respackopts$prefix = "\n//include " + Respackopts.RPO_SHADER_ID;
private static final String respackopts$prefix = "\n//include " + RespackoptsClient.RPO_SHADER_ID;
@ModifyArg(method = "readSource(Ljava/lang/String;)Ljava/util/List;", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gl/GLImportProcessor;parseImports(Ljava/lang/String;Lnet/minecraft/client/gl/GLImportProcessor$Context;Ljava/lang/String;)Ljava/util/List;"), index = 0)
private String modify(String value) {
return value.replace(respackopts$prefix, "\n" + Respackopts.getShaderImportSource());
return value.replace(respackopts$prefix, "\n" + RespackoptsClient.getShaderImportSource());
}
}

View File

@ -1,6 +1,7 @@
package io.gitlab.jfronny.respackopts.mixin;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.RespackoptsClient;
import net.minecraft.client.gui.screen.option.OptionsScreen;
import net.minecraft.client.option.GameOptions;
import net.minecraft.resource.ResourcePackManager;
@ -17,8 +18,8 @@ public class OptionsScreenMixin {
@Inject(at = @At("HEAD"), method = "refreshResourcePacks(Lnet/minecraft/resource/ResourcePackManager;)V")
private void refreshResourcePacks(ResourcePackManager resourcePackManager, CallbackInfo info) {
if (Respackopts.forcePackReload) {
Respackopts.forcePackReload = false;
if (RespackoptsClient.forcePackReload) {
RespackoptsClient.forcePackReload = false;
if (Respackopts.CONFIG.debugLogs)
Respackopts.LOGGER.info("Clearing loaded resource packs to enable a proper resource reload");
this.settings.resourcePacks.clear();

View File

@ -1,9 +1,9 @@
package io.gitlab.jfronny.respackopts.mixin;
import com.mojang.blaze3d.systems.RenderSystem;
import io.gitlab.jfronny.respackopts.RespackoptsClient;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.util.MetaCache;
import io.gitlab.jfronny.respackopts.Respackopts;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.gui.screen.pack.PackListWidget;
@ -18,8 +18,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.nio.file.Path;
@Mixin(PackListWidget.ResourcePackEntry.class)
public abstract class ResourcePackEntryMixin {
@Final @Shadow private PackListWidget widget;
@ -48,7 +46,7 @@ public abstract class ResourcePackEntryMixin {
if (dataLocation != null && rpo$selected) {
info.setReturnValue(true);
MinecraftClient c = MinecraftClient.getInstance();
c.setScreen(Respackopts.GUI_FACTORY.buildGui(MetaCache.getBranch(dataLocation), MetaCache.getId(dataLocation), c.currentScreen));
c.setScreen(RespackoptsClient.GUI_FACTORY.buildGui(MetaCache.getBranch(dataLocation), MetaCache.getId(dataLocation), c.currentScreen));
}
}
}

View File

@ -1,25 +1,28 @@
package io.gitlab.jfronny.respackopts;
package io.gitlab.jfronny.respackopts.util;
import io.gitlab.jfronny.respackopts.integration.*;
import io.gitlab.jfronny.respackopts.model.enums.*;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.integration.SaveHook;
import io.gitlab.jfronny.respackopts.model.enums.PackReloadType;
import io.gitlab.jfronny.respackopts.model.tree.*;
import io.gitlab.jfronny.respackopts.util.*;
import me.shedaniel.clothconfig2.api.*;
import net.minecraft.client.gui.screen.*;
import net.minecraft.text.*;
import net.minecraft.util.*;
import net.minecraft.client.gui.screen.FatalErrorScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text;
import net.minecraft.util.Language;
import java.util.*;
import java.util.function.*;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
public class GuiFactory {
public class GuiFactory implements CategoryFactory {
@Override
public void buildCategory(ConfigBranch source, String screenId, Consumer<AbstractConfigListEntry<?>> config, Consumer<PackReloadType> reloadTypeAggregator, ConfigEntryBuilder entryBuilder, String namePrefix) {
for (Map.Entry<String, ConfigEntry<?>> in : source.getValue().entrySet()) {
ConfigEntry<?> entry = in.getValue();
String entryName = ("".equals(namePrefix) ? "" : namePrefix + ".") + in.getKey();
String translationPrefix = (source.getVersion() < 3 ? "respackopts." + entry.getEntryType() + "." : "rpo.") + screenId;
config.accept(entry.buildEntry(
new GuiEntryBuilderParam(entryBuilder, getText(entryName, translationPrefix), () -> {
new GuiEntryBuilderParam(entryBuilder, entryName, () -> {
String k = (source.getVersion() < 3 ? "respackopts.tooltip." : "rpo.tooltip.") + screenId + "." + entryName;
if (Language.getInstance().hasTranslation(k)) {
Text[] res = new Text[1];
@ -27,35 +30,23 @@ public class GuiFactory {
return Optional.of(res);
} else
return Optional.empty();
}, screenId, entryName, translationPrefix, () -> reloadTypeAggregator.accept(entry.getReloadType()), reloadTypeAggregator)));
}, screenId, entryName, translationPrefix, () -> reloadTypeAggregator.accept(entry.getReloadType()), reloadTypeAggregator, this)));
}
}
public static Text getText(String name, String translationPrefix) {
String translatableNameKey = translationPrefix + "." + name;
return Language.getInstance().hasTranslation(translatableNameKey)
? Text.translatable(translatableNameKey)
: Text.literal(name);
}
public Screen buildGui(ConfigBranch source, String packId, Screen parent) {
try {
ConfigBuilder builder;
builder = ConfigBuilder.create()
.setParentScreen(parent)
.setTitle(getText(packId, source.getVersion() < 4 ? "respackopts.title" : "rpo"));
.setTitle(GuiEntryBuilderParam.getText(packId, source.getVersion() < 4 ? "respackopts.title" : "rpo"));
ConfigEntryBuilder entryBuilder = builder.entryBuilder();
PackReloadType.Aggregator agg = new PackReloadType.Aggregator();
builder.setSavingRunnable(() -> {
MetaCache.save();
if (Respackopts.CONFIG.debugLogs) Respackopts.LOGGER.info("GuiFactory SavingRunnable " + agg.get());
if (agg.get() == PackReloadType.Resource) {
Respackopts.forcePackReload = true;
DashLoaderCompat.requestForceReload();
Respackopts.reloadData();
}
MetaCache.save(new SaveHook.Arguments(agg.get() == PackReloadType.Resource, false, true));
});
ConfigCategory config = builder.getOrCreateCategory(getText(packId, source.getVersion() < 4 ? "respackopts.title" : "rpo"));
ConfigCategory config = builder.getOrCreateCategory(GuiEntryBuilderParam.getText(packId, source.getVersion() < 4 ? "respackopts.title" : "rpo"));
buildCategory(source, packId, config::addEntry, agg, entryBuilder, "");
return builder.build();
}

View File

@ -0,0 +1,15 @@
{
"required": true,
"minVersion": "0.8",
"package": "io.gitlab.jfronny.respackopts.mixin",
"compatibilityLevel": "JAVA_8",
"client": [
"GLImportProcessorMixin",
"OptionsScreenMixin",
"PackScreenMixin",
"ResourcePackEntryMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@ -1,28 +1,29 @@
package io.gitlab.jfronny.respackopts;
import io.gitlab.jfronny.gson.*;
import io.gitlab.jfronny.gson.Gson;
import io.gitlab.jfronny.gson.GsonBuilder;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.respackopts.filters.*;
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.*;
import io.gitlab.jfronny.respackopts.integration.*;
import io.gitlab.jfronny.respackopts.model.*;
import io.gitlab.jfronny.respackopts.integration.SaveHook;
import io.gitlab.jfronny.respackopts.model.Condition;
import io.gitlab.jfronny.respackopts.model.ConfigFile;
import io.gitlab.jfronny.respackopts.model.tree.*;
import io.gitlab.jfronny.respackopts.util.*;
import io.gitlab.jfronny.respackopts.server.ServerInstanceHolder;
import net.fabricmc.api.*;
import net.fabricmc.loader.api.*;
import net.minecraft.client.*;
import net.minecraft.server.integrated.*;
import net.minecraft.util.*;
import org.slf4j.*;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.util.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.CompletableFuture;
@Environment(EnvType.CLIENT)
public class Respackopts implements ClientModInitializer {
public class Respackopts implements ModInitializer, SaveHook {
public static final Integer META_VERSION = 8;
public static final String FILE_EXTENSION = ".rpo";
public static final Gson GSON;
@ -30,14 +31,9 @@ public class Respackopts implements ClientModInitializer {
public static final String ID = "respackopts";
public static final Logger LOGGER = LoggerFactory.getLogger(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()
@ -61,31 +57,26 @@ public class Respackopts implements ClientModInitializer {
}
@Override
public void onInitializeClient() {
public void onInitialize() {
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(() -> {
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((key, state) -> state.configBranch().buildShader(sb, sanitizeString(state.packId())));
sb.append("\n#endif");
shaderImportSource = sb.toString();
});
DirFilterEventImpl.init();
FileFilterEventImpl.init();
if (CONFIG.debugCommands)
RpoCommand.register();
if (FabricLoader.getInstance().isModLoaded("frex")) {
FrexCompat.onInitializeFrex();
ServerInstanceHolder.init();
}
@Override
public CompletableFuture<Void> onSave(Arguments args) {
CONFIG.save();
if (args.reloadData() && FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) {
ServerInstanceHolder.reloadResources();
}
return CompletableFuture.completedFuture(null);
}
public static String sanitizeString(String s) {
@ -99,28 +90,4 @@ public class Respackopts implements ClientModInitializer {
// [^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;
}
}

View File

@ -1,54 +0,0 @@
package io.gitlab.jfronny.respackopts;
import io.gitlab.jfronny.respackopts.util.*;
import net.fabricmc.fabric.api.client.command.v2.*;
import net.fabricmc.loader.api.*;
import net.minecraft.text.*;
import java.io.*;
import java.nio.file.*;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*;
public class RpoCommand {
private static final ModContainer CONTAINER = FabricLoader.getInstance().getModContainer(Respackopts.ID).get();
public static void register() {
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
dispatcher.register(literal("rpo").then(literal("dump").then(literal("glsl").executes(ctx -> {
ctx.getSource().sendFeedback(dump(Respackopts.getShaderImportSource(), "frex.glsl"));
return 1;
}))));
dispatcher.register(literal("rpo").then(literal("dump").then(literal("config").executes(ctx -> {
MetaCache.forEach((id, branch) -> ctx.getSource().sendFeedback(dump(branch.toString(), id + ".txt")));
return 1;
}))));
dispatcher.register(literal("rpo").then(literal("dump").executes(ctx -> {
MetaCache.forEach((id, branch) -> ctx.getSource().sendFeedback(dump(branch.toString(), id + ".txt")));
return 1;
})));
dispatcher.register(literal("rpo").then(literal("version").executes(ctx -> {
ctx.getSource().sendFeedback(Text.translatable("respackopts.versionText", CONTAINER.getMetadata().getVersion(), Respackopts.META_VERSION));
return 1;
})));
dispatcher.register(literal("rpo").executes(ctx -> {
ctx.getSource().sendFeedback(Text.translatable("respackopts.versionText", CONTAINER.getMetadata().getVersion(), Respackopts.META_VERSION));
return 1;
}));
});
}
private static final Path dumpPath = FabricLoader.getInstance().getGameDir().resolve("respackopts");
private static Text dump(String text, String fileName) {
try {
if (!Files.exists(dumpPath)) Files.createDirectories(dumpPath);
Path filePath = dumpPath.resolve(fileName);
try (BufferedWriter bw = Files.newBufferedWriter(filePath, StandardOpenOption.CREATE)) {
bw.write(text);
}
return Text.translatable("respackopts.dumpSucceeded", filePath.toAbsolutePath());
}
catch (Throwable e) {
return Text.translatable("respackopts.dumpFailed");
}
}
}

View File

@ -1,13 +1,13 @@
package io.gitlab.jfronny.respackopts.filters.util;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
import io.gitlab.jfronny.respackopts.*;
import io.gitlab.jfronny.respackopts.util.*;
import net.minecraft.resource.*;
import io.gitlab.jfronny.commons.data.dynamic.Dynamic;
import io.gitlab.jfronny.muscript.compiler.expr.StringExpr;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.util.MetaCache;
import net.minecraft.resource.ResourcePack;
import java.io.*;
import java.util.*;
import java.util.Map;
public class FileExpansionProvider {
public static synchronized InputStream replace(Dynamic<?> parameter, InputStream is, Map<String, StringExpr> expansions) throws IOException {

View File

@ -1,13 +0,0 @@
package io.gitlab.jfronny.respackopts.integration;
import io.gitlab.jfronny.commons.throwable.*;
import io.gitlab.jfronny.respackopts.*;
import io.vram.frex.api.config.*;
public class FrexCompat {
public static void onInitializeFrex() {
ShaderConfig.registerShaderConfigSupplier(Respackopts.RPO_SHADER_ID, Respackopts::getShaderImportSource);
Respackopts.LOGGER.info("enabled frex/canvas support");
Respackopts.SAVE_ACTIONS.add(Try.handle(ShaderConfig::invalidateShaderConfig, e -> Respackopts.LOGGER.error("Could not reload shader config", e)));
}
}

View File

@ -0,0 +1,12 @@
package io.gitlab.jfronny.respackopts.integration;
import java.util.concurrent.CompletableFuture;
public interface SaveHook {
CompletableFuture<Void> onSave(Arguments args);
record Arguments(boolean flagResourcesForReload, boolean reloadResourcesImmediately, boolean reloadData) {
public static final Arguments DO_NOTHING = new Arguments(false, false, false);
public static final Arguments RELOAD_ALL = new Arguments(true, true, true);
}
}

View File

@ -1,5 +1,6 @@
package io.gitlab.jfronny.respackopts.mixin;
import io.gitlab.jfronny.respackopts.integration.SaveHook;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.util.MetaCache;
import io.gitlab.jfronny.respackopts.Respackopts;
@ -67,6 +68,6 @@ public class ResourcePackManagerMixin {
CacheKey k = MetaCache.getKeyByDataLocation(s);
if (k != null) MetaCache.remove(k);
}
MetaCache.save();
MetaCache.save(SaveHook.Arguments.DO_NOTHING);
}
}

View File

@ -1,7 +1,7 @@
package io.gitlab.jfronny.respackopts.model;
import io.gitlab.jfronny.commons.data.dynamic.Dynamic;
import io.gitlab.jfronny.muscript.compiler.expr.*;
import io.gitlab.jfronny.muscript.dynamic.*;
import io.gitlab.jfronny.muscript.error.*;
public record Condition(String source, BoolExpr expr) {

View File

@ -1,7 +1,6 @@
package io.gitlab.jfronny.respackopts.model.cache;
import io.gitlab.jfronny.muscript.*;
import io.gitlab.jfronny.muscript.dynamic.*;
import io.gitlab.jfronny.muscript.ExpressionParameter;
import io.gitlab.jfronny.respackopts.model.DirRpo;
import io.gitlab.jfronny.respackopts.model.FileRpo;
import io.gitlab.jfronny.respackopts.model.PackMeta;

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.respackopts.model.tree;
import io.gitlab.jfronny.muscript.dynamic.*;
import io.gitlab.jfronny.commons.data.dynamic.DBool;
import io.gitlab.jfronny.respackopts.Respackopts;
import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
@ -34,17 +34,17 @@ public class ConfigBooleanEntry extends ConfigEntry<Boolean> {
}
@Override
public AbstractConfigListEntry<?> buildEntry(GuiEntryBuilderParam guiEntryBuilderParam) {
return guiEntryBuilderParam.entryBuilder().startBooleanToggle(guiEntryBuilderParam.name(), getValue())
public AbstractConfigListEntry<?> buildEntry(GuiEntryBuilderParam args) {
return args.entryBuilder().startBooleanToggle(args.getName(), getValue())
.setDefaultValue(getDefault())
.setSaveConsumer(value -> {
if (getValue() != value) {
if (Respackopts.CONFIG.debugLogs) Respackopts.LOGGER.info("ConfigBooleanEntry SaveCallback");
guiEntryBuilderParam.saveCallback();
args.saveCallback();
}
setValue(value);
})
.setTooltipSupplier(guiEntryBuilderParam.tooltipSupplier())
.setTooltipSupplier(args.tooltipSupplier())
.build();
}

View File

@ -1,8 +1,8 @@
package io.gitlab.jfronny.respackopts.model.tree;
import com.google.common.collect.ImmutableMap;
import io.gitlab.jfronny.commons.data.dynamic.*;
import io.gitlab.jfronny.gson.reflect.TypeToken;
import io.gitlab.jfronny.muscript.dynamic.*;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.util.IndentingStringBuilder;
@ -121,10 +121,10 @@ public class ConfigBranch extends ConfigEntry<Map<String, ConfigEntry<?>>> {
}
@Override
public AbstractConfigListEntry<?> buildEntry(GuiEntryBuilderParam guiEntryBuilderParam) {
SubCategoryBuilder sc = guiEntryBuilderParam.entryBuilder().startSubCategory(guiEntryBuilderParam.name());
Respackopts.GUI_FACTORY.buildCategory(this, guiEntryBuilderParam.screenId(), sc::add, guiEntryBuilderParam.agg(), guiEntryBuilderParam.entryBuilder(), guiEntryBuilderParam.entryName());
sc.setTooltipSupplier(guiEntryBuilderParam.tooltipSupplier());
public AbstractConfigListEntry<?> buildEntry(GuiEntryBuilderParam args) {
SubCategoryBuilder sc = args.entryBuilder().startSubCategory(args.getName());
args.buildCategory(this, args.screenId(), sc::add, args.agg(), args.entryBuilder(), args.entryName());
sc.setTooltipSupplier(args.tooltipSupplier());
return sc.build();
}

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.respackopts.model.tree;
import io.gitlab.jfronny.muscript.dynamic.*;
import io.gitlab.jfronny.commons.data.dynamic.Dynamic;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.model.enums.PackReloadType;
@ -104,7 +104,7 @@ public abstract class ConfigEntry<T> {
public abstract Dynamic<?> getDynamic();
public abstract AbstractConfigListEntry<?> buildEntry(GuiEntryBuilderParam guiEntryBuilderParam);
public abstract AbstractConfigListEntry<?> buildEntry(GuiEntryBuilderParam args);
public String getEntryType() {
return "field";

View File

@ -1,14 +1,14 @@
package io.gitlab.jfronny.respackopts.model.tree;
import io.gitlab.jfronny.muscript.dynamic.*;
import io.gitlab.jfronny.respackopts.*;
import io.gitlab.jfronny.respackopts.model.enums.*;
import io.gitlab.jfronny.respackopts.util.*;
import me.shedaniel.clothconfig2.api.*;
import net.minecraft.text.*;
import io.gitlab.jfronny.commons.data.dynamic.DEnum;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.util.IndentingStringBuilder;
import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
import net.minecraft.text.Text;
import java.util.*;
import java.util.function.*;
import java.util.function.Function;
public class ConfigEnumEntry extends ConfigEntry<String> {
public List<String> values = new ArrayList<>();
@ -118,15 +118,14 @@ public class ConfigEnumEntry extends ConfigEntry<String> {
}
@Override
public AbstractConfigListEntry<?> buildEntry(GuiEntryBuilderParam guiEntryBuilderParam) {
Function<String, Text> entryText = s -> GuiFactory.getText(s, ("".equals(guiEntryBuilderParam.translationPrefix()) ? "" : guiEntryBuilderParam.translationPrefix() + ".") + guiEntryBuilderParam.entryName());
public AbstractConfigListEntry<?> buildEntry(GuiEntryBuilderParam args) {
Map<String, String> translationReverseLookup = new HashMap<>();
for (String value : values) {
translationReverseLookup.put(entryText.apply(value).getString(), value);
translationReverseLookup.put(args.prefixWithName(value).getString(), value);
}
return guiEntryBuilderParam.entryBuilder().startStringDropdownMenu(guiEntryBuilderParam.name(), entryText.apply(getValue()).getString(), entryText)
return args.entryBuilder().startStringDropdownMenu(args.getName(), args.prefixWithName(getValue()).getString(), args::prefixWithName)
.setSuggestionMode(false)
.setDefaultValue(entryText.apply(getDefault()).getString())
.setDefaultValue(args.prefixWithName(getDefault()).getString())
.setSelections(translationReverseLookup.keySet())
.setSaveConsumer(value -> {
if (!translationReverseLookup.containsKey(value)) {
@ -136,11 +135,11 @@ public class ConfigEnumEntry extends ConfigEntry<String> {
value = translationReverseLookup.get(value);
if (!Objects.equals(getValue(), value)) {
if (Respackopts.CONFIG.debugLogs) Respackopts.LOGGER.info("ConfigEnumEntry SaveCallback");
guiEntryBuilderParam.saveCallback();
args.saveCallback();
}
setValue(value);
})
.setTooltipSupplier(guiEntryBuilderParam.tooltipSupplier())
.setTooltipSupplier(args.tooltipSupplier())
.build();
}

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.respackopts.model.tree;
import io.gitlab.jfronny.muscript.dynamic.*;
import io.gitlab.jfronny.commons.data.dynamic.DNumber;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.model.enums.NumericEntryType;
@ -72,32 +72,32 @@ public class ConfigNumericEntry extends ConfigEntry<Double> {
}
@Override
public AbstractConfigListEntry<?> buildEntry(GuiEntryBuilderParam guiEntryBuilderParam) {
public AbstractConfigListEntry<?> buildEntry(GuiEntryBuilderParam args) {
if (type == NumericEntryType.Slider) {
return guiEntryBuilderParam.entryBuilder().startIntSlider(guiEntryBuilderParam.name(),
return args.entryBuilder().startIntSlider(args.getName(),
getValue().intValue(), min.intValue(), max.intValue())
.setDefaultValue(getDefault().intValue())
.setSaveConsumer(value -> {
if (!Objects.equals(getValue(), value.doubleValue())) {
if (Respackopts.CONFIG.debugLogs) Respackopts.LOGGER.info("ConfigNumericEntrySlider SaveCallback");
guiEntryBuilderParam.saveCallback();
args.saveCallback();
}
setValue(value.doubleValue());
})
.setTooltipSupplier(guiEntryBuilderParam.tooltipSupplier())
.setTooltipSupplier(args.tooltipSupplier())
.build();
}
else {
DoubleFieldBuilder builder = guiEntryBuilderParam.entryBuilder().startDoubleField(guiEntryBuilderParam.name(), getValue())
DoubleFieldBuilder builder = args.entryBuilder().startDoubleField(args.getName(), getValue())
.setDefaultValue(getDefault())
.setSaveConsumer(value -> {
if (!Objects.equals(getValue(), value)) {
if (Respackopts.CONFIG.debugLogs) Respackopts.LOGGER.info("ConfigNumericEntryNormal SaveCallback");
guiEntryBuilderParam.saveCallback();
args.saveCallback();
}
setValue(value);
})
.setTooltipSupplier(guiEntryBuilderParam.tooltipSupplier());
.setTooltipSupplier(args.tooltipSupplier());
if (min != null) builder.setMin(min);
if (max != null) builder.setMax(max);
return builder.build();

View File

@ -1,17 +1,45 @@
package io.gitlab.jfronny.respackopts.model.tree;
import io.gitlab.jfronny.respackopts.model.enums.PackReloadType;
import io.gitlab.jfronny.respackopts.util.CategoryFactory;
import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
import net.minecraft.text.Text;
import net.minecraft.util.Language;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
public record GuiEntryBuilderParam(ConfigEntryBuilder entryBuilder, Text name,
public record GuiEntryBuilderParam(ConfigEntryBuilder entryBuilder, String name,
Supplier<Optional<Text[]>> tooltipSupplier, String screenId, String entryName,
String translationPrefix, Runnable onSave, Consumer<PackReloadType> agg) {
String translationPrefix, Runnable onSave, Consumer<PackReloadType> agg,
CategoryFactory categoryFactory) implements CategoryFactory {
public void saveCallback() {
onSave.run();
}
public Text getName() {
return getText(name);
}
public Text prefixWithName(String subName) {
return getText(subName, translationPrefix.equals("") ? name : translationPrefix + "." + name);
}
public Text getText(String name) {
return getText(name, translationPrefix);
}
public static Text getText(String name, String translationPrefix) {
String translatableNameKey = translationPrefix + "." + name;
return Language.getInstance().hasTranslation(translatableNameKey)
? Text.translatable(translatableNameKey)
: Text.literal(name);
}
@Override
public void buildCategory(ConfigBranch source, String screenId, Consumer<AbstractConfigListEntry<?>> config, Consumer<PackReloadType> reloadTypeAggregator, ConfigEntryBuilder entryBuilder, String namePrefix) {
categoryFactory.buildCategory(source, screenId, config, reloadTypeAggregator, entryBuilder, namePrefix);
}
}

View File

@ -0,0 +1,57 @@
package io.gitlab.jfronny.respackopts.server;
import com.google.common.collect.Lists;
import io.gitlab.jfronny.commons.ref.WeakSet;
import io.gitlab.jfronny.respackopts.Respackopts;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.minecraft.resource.ResourcePackManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.SaveProperties;
import java.util.List;
import java.util.Set;
public class ServerInstanceHolder {
private static final Set<MinecraftServer> SERVERS = new WeakSet<>();
public static void init() {
ServerLifecycleEvents.SERVER_STARTED.register(server -> {
if (!SERVERS.isEmpty()) {
Respackopts.LOGGER.warn("Multiple servers started at once. This is unexpected");
}
if (!SERVERS.add(server)) {
Respackopts.LOGGER.warn("Called SERVER_STARTED on a server that is already started");
}
});
ServerLifecycleEvents.SERVER_STOPPED.register(server -> {
if (!SERVERS.remove(server)) {
Respackopts.LOGGER.warn("Called SERVER_STOPPED on a server that was never started/already stopped");
}
if (!SERVERS.isEmpty()) {
Respackopts.LOGGER.warn("Server stopped but another one is still running. This is unexpected");
}
});
}
public static void reloadResources() {
if (SERVERS.isEmpty()) {
Respackopts.LOGGER.warn("Attempted to reload resources while no server is running. Skipping");
}
for (MinecraftServer server : SERVERS) {
ResourcePackManager manager = server.getDataPackManager();
SaveProperties saveProperties = server.getSaveProperties();
List<String> enabled = Lists.newArrayList(manager.getEnabledNames());
manager.scanPacks();
List<String> disabled = saveProperties.getDataPackSettings().getDisabled();
for (String name : manager.getNames()) {
if (!disabled.contains(name) && !enabled.contains(name)) {
enabled.add(name);
}
}
server.reloadResources(enabled).exceptionally(throwable -> {
Respackopts.LOGGER.warn("Failed to reload data packs", throwable);
return null;
});
}
}
}

View File

@ -0,0 +1,12 @@
package io.gitlab.jfronny.respackopts.util;
import io.gitlab.jfronny.respackopts.model.enums.PackReloadType;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch;
import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
import java.util.function.Consumer;
public interface CategoryFactory {
void buildCategory(ConfigBranch source, String screenId, Consumer<AbstractConfigListEntry<?>> config, Consumer<PackReloadType> reloadTypeAggregator, ConfigEntryBuilder entryBuilder, String namePrefix);
}

View File

@ -1,21 +1,25 @@
package io.gitlab.jfronny.respackopts.util;
import io.gitlab.jfronny.commons.throwable.*;
import io.gitlab.jfronny.muscript.*;
import io.gitlab.jfronny.muscript.dynamic.*;
import io.gitlab.jfronny.respackopts.*;
import io.gitlab.jfronny.respackopts.model.*;
import io.gitlab.jfronny.respackopts.model.cache.*;
import io.gitlab.jfronny.respackopts.model.enums.*;
import io.gitlab.jfronny.respackopts.model.tree.*;
import net.fabricmc.loader.api.*;
import net.fabricmc.loader.api.metadata.version.*;
import net.minecraft.resource.*;
import org.jetbrains.annotations.*;
import io.gitlab.jfronny.commons.throwable.ThrowingBiConsumer;
import io.gitlab.jfronny.muscript.ExpressionParameter;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.integration.SaveHook;
import io.gitlab.jfronny.respackopts.model.PackMeta;
import io.gitlab.jfronny.respackopts.model.cache.CacheKey;
import io.gitlab.jfronny.respackopts.model.cache.CachedPackState;
import io.gitlab.jfronny.respackopts.model.enums.ConfigSyncMode;
import io.gitlab.jfronny.respackopts.model.enums.PackCapability;
import io.gitlab.jfronny.respackopts.model.tree.ConfigBranch;
import net.fabricmc.api.EnvType;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.resource.ResourcePack;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.nio.file.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.CompletableFuture;
public class MetaCache {
private static final Map<CacheKey, CachedPackState> PACK_STATES = new HashMap<>();
@ -32,6 +36,13 @@ public class MetaCache {
PACK_STATES.remove(key);
}
public static void clear() {
PACK_STATES.clear();
KEYS_BY_DISPLAY_NAME.clear();
KEYS_BY_PACK_NAME.clear();
KEYS_BY_DATA_LOCATION.clear();
}
public static void addFromScan(String displayName, String packName, PackMeta meta, Path dataLocation) {
if (Respackopts.META_VERSION > meta.version) {
Respackopts.LOGGER.warn(displayName + " uses an outdated RPO format (" + meta.version + "). Although this is supported, using the latest version (" + Respackopts.META_VERSION + ") is recommended");
@ -69,15 +80,22 @@ public class MetaCache {
save(dataLocation, meta.conf);
}
public static void save() {
public static CompletableFuture<Void> save(SaveHook.Arguments args) {
if (Respackopts.CONFIG.debugLogs)
Respackopts.LOGGER.info("Saving configs");
for (Map.Entry<CacheKey, CachedPackState> e : PACK_STATES.entrySet()) {
save(e.getKey().dataLocation(), e.getValue().configBranch());
}
for (Runnable action : Respackopts.SAVE_ACTIONS) {
action.run();
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (SaveHook hook : FabricLoader.getInstance().getEntrypoints(Respackopts.ID + ":save_hook", SaveHook.class)) {
futures.add(hook.onSave(args));
}
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
for (SaveHook hook : FabricLoader.getInstance().getEntrypoints(Respackopts.ID + ":client_save_hook", SaveHook.class)) {
futures.add(hook.onSave(args));
}
}
return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new));
}
private static void save(Path dataLocation, ConfigBranch branch) {

View File

@ -1,13 +1,16 @@
package io.gitlab.jfronny.respackopts.util;
import io.gitlab.jfronny.muscript.*;
import io.gitlab.jfronny.muscript.dynamic.*;
import net.fabricmc.loader.api.*;
import net.fabricmc.loader.api.metadata.version.*;
import io.gitlab.jfronny.commons.data.dynamic.*;
import io.gitlab.jfronny.muscript.ExpressionParameter;
import io.gitlab.jfronny.muscript.StandardLib;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.VersionParsingException;
import net.fabricmc.loader.api.metadata.version.VersionPredicate;
import java.time.*;
import java.util.*;
import java.util.function.*;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Map;
import java.util.function.Supplier;
public class MuUtils {
public static ExpressionParameter addDefault(ExpressionParameter parameter) {

View File

@ -7,7 +7,9 @@
"respackopts.mainconfig.debugLogs": "Debug Logs",
"respackopts.mainconfig.dashloaderCompat": "Dashloader compatibility",
"respackopts.invalid": "Invalid value",
"respackopts.dumpFailed": "Could not dump the requested resource, look at your log for details",
"respackopts.dumpSucceeded": "Successfully dumped the resource to %s",
"respackopts.dumpFailed": "Could not dump the requested resource, look at your log for details",
"respackopts.reloadSucceeded": "Successfully reloaded resources and data",
"respackopts.reloadFailed": "Could not reload all resources, look at your log for details",
"respackopts.versionText": "Version %s using the respackotps meta version %s"
}

View File

@ -12,24 +12,37 @@
"icon": "assets/respackopts/icon.png",
"environment": "client",
"entrypoints": {
"client": [
"main": [
"io.gitlab.jfronny.respackopts.Respackopts"
],
"client": [
"io.gitlab.jfronny.respackopts.RespackoptsClient"
],
"modmenu": [
"io.gitlab.jfronny.respackopts.integration.ModMenuCompat"
],
"frex": [
"io.gitlab.jfronny.respackopts.integration.FrexCompat"
],
"respackopts:save_hook": [
"io.gitlab.jfronny.respackopts.Respackopts"
],
"respackopts:client_save_hook": [
"io.gitlab.jfronny.respackopts.RespackoptsClient"
]
},
"mixins": [
"respackopts.mixins.json"
"respackopts.mixins.json",
{
"config": "respackopts.client.mixins.json",
"environment": "client"
}
],
"depends": {
"fabricloader": ">=0.12.0",
"fabric": "*",
"minecraft": "*",
"cloth-config2": ">=5.0.0",
"cloth-config2": ">=7.0.0",
"libjf-data-manipulation-v0": ">=2.0",
"libjf-base": ">=2.0"
},

View File

@ -7,12 +7,6 @@
"AbstractFileResourcePackAccessor",
"ResourcePackManagerMixin"
],
"client": [
"GLImportProcessorMixin",
"OptionsScreenMixin",
"PackScreenMixin",
"ResourcePackEntryMixin"
],
"injectors": {
"defaultRequire": 1
}