Utilize reflection in DashLoader compat, re-enable canvas dependency, add /rpo command, document frex integration, bump version

This commit is contained in:
JFronny 2021-09-14 19:42:38 +02:00
parent 45f0bbf5b9
commit dfbc52625c
No known key found for this signature in database
GPG Key ID: BEC5ACBBD4EE17E5
11 changed files with 139 additions and 26 deletions

View File

@ -26,16 +26,11 @@ dependencies {
include modImplementation("com.github.MeteorDevelopment:starscript:0.1.5")
modApi("me.shedaniel.cloth:cloth-config-fabric:5.0.38")
modCompileOnly "grondag:frex-mc117:+"
//modRuntime("grondag:canvas-mc117-1.17:+") {
// exclude(group: "me.shedaniel.cloth")
//}
modRuntime("grondag:canvas-mc117-1.17:+") {
exclude(group: "me.shedaniel.cloth")
}
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
//DashLoader "compatibility"
modImplementation ('net.oskarstrom:DashLoader:2.1-dev7') {
exclude group: 'net.fabricmc.fabric-api'
}
}
test {

25
docs/Canvas.md Normal file
View File

@ -0,0 +1,25 @@
# Canvas/FREX integration
## Background
The FREX shader API (which shaders targeting the Canvas renderer utilize) allows other mods to register config code which shaders may `#include`.
Respackopts is one of such mods and utilizes this feature to expose the packs respackopts config.
## Getting started
All you need to do to access respackotps values is paste the following in a file where you want them: `#include respackopts:config_supplier`
However, usually you will want to still have a pack that works if respackotps is not present. In that case, canvas will still load the file,
however, values that respackotps registers will not be available leading to compile errors.
To avoid this, I recommend creating a source file in your own shader which will load default values if respackotps isn't present. You can do that as follows:
```
#include respackopts:config_supplier
#ifdef respackopts_loaded
// define your default values here
// Example:
// #define examplePack_someTexture
#endif
```
You will then need to include this file in the places you want to access its values.
## 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 frex` command in minecraft.
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,4 +1,4 @@
# ResPackOpts Multi File Toggle (Multi Selction)
# ResPackOpts Multi File Toggle (Multi Selection)
This Allows you to pick between multiple files (3 or more files) using similar logic to [Toggle Files](./ToggleFiles.md)
But this requires multiple `.rpo` files to achieve the desired goal.

View File

@ -7,7 +7,7 @@ However, the quality of the documentation here is worse.
| --- | --- |
| home | done |
| adding_entries | done |
| canvas | TODO |
| canvas | done |
| conditional | TODO explain advanced conditions/condition arrays |
| expand | TODO |
| fallbacks | TODO: explain multiple fallbacks for files |

View File

@ -6,7 +6,7 @@ minecraft_version=1.17.1
yarn_mappings=build.43
loader_version=0.11.6
# Mod Properties
mod_version=2.6.0
mod_version=2.7.0
maven_group=io.gitlab.jfronny
archives_base_name=respackopts

View File

@ -3,6 +3,7 @@ package io.gitlab.jfronny.respackopts;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.gitlab.jfronny.libjf.data.WrappedPack;
import io.gitlab.jfronny.respackopts.command.RpoCommand;
import io.gitlab.jfronny.respackopts.data.DirRpo;
import io.gitlab.jfronny.respackopts.data.PackCapability;
import io.gitlab.jfronny.respackopts.data.Respackmeta;
@ -107,6 +108,7 @@ public class Respackopts implements ClientModInitializer {
});
DirFilterProvider.init();
FileFilterProvider.init();
RpoCommand.register();
}
public static void save() {

View File

@ -0,0 +1,62 @@
package io.gitlab.jfronny.respackopts.command;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.data.entry.ConfigBranch;
import io.gitlab.jfronny.respackopts.integration.FrexCompat;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import java.io.BufferedWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Map;
import static net.fabricmc.fabric.api.client.command.v1.ClientCommandManager.*;
public class RpoCommand {
private static final ModContainer respackotps = FabricLoader.getInstance().getModContainer(Respackopts.ID).get();
public static void register() {
DISPATCHER.register(literal("rpo").then(literal("dump").then(literal("frex").executes(ctx -> {
ctx.getSource().sendFeedback(dump(FrexCompat.generateShader(), "frex.frag"));
return 1;
}))));
DISPATCHER.register(literal("rpo").then(literal("dump").then(literal("config").executes(ctx -> {
for (Map.Entry<String, ConfigBranch> entry : Respackopts.CONFIG_BRANCH.entrySet()) {
ctx.getSource().sendFeedback(dump(entry.getValue().toString(), entry.getKey() + ".txt"));
}
return 1;
}))));
DISPATCHER.register(literal("rpo").then(literal("dump").executes(ctx -> {
for (Map.Entry<String, ConfigBranch> entry : Respackopts.CONFIG_BRANCH.entrySet()) {
ctx.getSource().sendFeedback(dump(entry.getValue().toString(), entry.getKey() + ".txt"));
}
return 1;
})));
DISPATCHER.register(literal("rpo").then(literal("version").executes(ctx -> {
ctx.getSource().sendFeedback(new TranslatableText("respackopts.versionText", respackotps.getMetadata().getVersion(), Respackopts.META_VERSION));
return 1;
})));
DISPATCHER.register(literal("rpo").executes(ctx -> {
ctx.getSource().sendFeedback(new TranslatableText("respackopts.versionText", respackotps.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 new TranslatableText("respackopts.dumpSucceeded", filePath.toAbsolutePath());
}
catch (Throwable e) {
return new TranslatableText("respackopts.dumpFailed");
}
}
}

View File

@ -1,21 +1,45 @@
package io.gitlab.jfronny.respackopts.integration;
import net.oskarstrom.dashloader.util.enums.DashCachePaths;
import io.gitlab.jfronny.respackopts.Respackopts;
import net.fabricmc.loader.api.FabricLoader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
public class DashLoaderCompat {
public static boolean modPresent = FabricLoader.getInstance().isModLoaded("dashloader");
public static boolean forceReload = false;
private static final Set<Path> dashCachePaths = new HashSet<>();
static {
if (modPresent) {
try {
Class<?> dashCachePaths = Class.forName("net.oskarstrom.dashloader.util.enums.DashCachePaths");
Method getPath = dashCachePaths.getDeclaredMethod("getPath");
for (Object value : dashCachePaths.getEnumConstants()) {
DashLoaderCompat.dashCachePaths.add((Path) getPath.invoke(value));
}
}
catch (Throwable e) {
Respackopts.LOGGER.error("Failed to initialize rpos dashloader compat, please report this to JFronny");
}
}
}
// Called from ASM injected through mixin/dashloader/Plugin
public static void injection() {
if (DashLoaderCompat.forceReload)
for (DashCachePaths value : DashCachePaths.values()) {
if (DashLoaderCompat.forceReload) {
for (Path dashloaderPath : dashCachePaths) {
try {
Files.deleteIfExists(value.getPath());
Files.deleteIfExists(dashloaderPath);
} catch (IOException e) {
e.printStackTrace();
}
}
}
DashLoaderCompat.forceReload = false;
}
}

View File

@ -12,14 +12,7 @@ public class FrexCompat implements FrexInitializer {
boolean initial = true;
@Override
public void onInitalizeFrex() {
ShaderConfig.registerShaderConfigSupplier(new Identifier(Respackopts.ID, "config_supplier"), () -> {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, ConfigBranch> e : Respackopts.CONFIG_BRANCH.entrySet()) {
e.getValue().buildShader(sb, Respackopts.sanitizeString(e.getKey()));
}
sb.append("\n#define respackopts_loaded");
return sb.toString();
});
ShaderConfig.registerShaderConfigSupplier(new Identifier(Respackopts.ID, "config_supplier"), FrexCompat::generateShader);
Respackopts.LOGGER.info("enabled frex/canvas support");
Respackopts.SAVE_ACTIONS.add(() -> {
try {
@ -32,4 +25,13 @@ public class FrexCompat implements FrexInitializer {
}
});
}
public static String generateShader() {
StringBuilder sb = new StringBuilder();
sb.append("#define respackopts_loaded");
for (Map.Entry<String, ConfigBranch> e : Respackopts.CONFIG_BRANCH.entrySet()) {
e.getValue().buildShader(sb, Respackopts.sanitizeString(e.getKey()));
}
return sb.toString();
}
}

View File

@ -1,7 +1,7 @@
package io.gitlab.jfronny.respackopts.mixin.dashloader;
import io.gitlab.jfronny.respackopts.Respackopts;
import net.fabricmc.loader.api.FabricLoader;
import io.gitlab.jfronny.respackopts.integration.DashLoaderCompat;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
@ -21,7 +21,7 @@ import java.util.Set;
public class Plugin implements IMixinConfigPlugin {
@Override
public void onLoad(String mixinPackage) {
if (FabricLoader.getInstance().isModLoaded("dashloader")) {
if (DashLoaderCompat.modPresent) {
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class<?> classLoaderClass = classLoader.getClass();

View File

@ -4,5 +4,8 @@
"respackopts.configure": "Configure",
"respackopts.mainconfig": "ResPackOpts",
"respackopts.invalid": "Invalid value",
"respackopts.noPack": "No resource pack that supports RPO could be found. Install one and it will appear here"
"respackopts.noPack": "No resource pack that supports RPO could be found. Install one and it will appear here",
"respackopts.dumpFailed": "Could not dump the requested resource, look at your log for details",
"respackopts.dumpSucceeded": "Successfully dumped the resource to %s",
"respackopts.versionText": "Version %s using the respackotps meta version %s"
}