diff --git a/fabric/build.gradle b/fabric/build.gradle index 8cedb676..a7d20969 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -32,6 +32,7 @@ dependencies { modIncludeImplementation(fabricApi.module("fabric-api-base", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modIncludeImplementation(fabricApi.module("fabric-lifecycle-events-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modIncludeImplementation(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } + modImplementation(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } // Remove the next line if you don't want to depend on the API // modApi "me.shedaniel:architectury-fabric:${rootProject.architectury_version}" diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/fabric_resourcepacks/ModNioResourcePackMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/fabric_resourcepacks/ModNioResourcePackMixin.java new file mode 100644 index 00000000..e0cd8827 --- /dev/null +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/fabric_resourcepacks/ModNioResourcePackMixin.java @@ -0,0 +1,63 @@ +package org.embeddedt.modernfix.fabric.mixin.perf.fabric_resourcepacks; + +import net.fabricmc.fabric.impl.resource.loader.ModNioResourcePack; +import net.fabricmc.loader.api.metadata.ModMetadata; +import net.minecraft.server.packs.PackType; +import org.embeddedt.modernfix.ModernFix; +import org.embeddedt.modernfix.annotation.RequiresMod; +import org.embeddedt.modernfix.resources.PackResourcesCacheEngine; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.nio.file.Path; +import java.util.List; +import java.util.Set; + +@Mixin(ModNioResourcePack.class) +@RequiresMod("fabric-resource-loader-v0") +public abstract class ModNioResourcePackMixin { + @Shadow public abstract Set getNamespaces(PackType type); + + @Shadow @Final private List basePaths; + @Shadow @Final private ModMetadata modInfo; + private PackResourcesCacheEngine cacheEngine; + + @Inject(method = "", at = @At("RETURN")) + private void cacheResources(CallbackInfo ci) { + if(this.basePaths.size() == 1) { + Path basePath = this.basePaths.get(0); + this.cacheEngine = new PackResourcesCacheEngine(this::getNamespaces, (type, namespace) -> { + return basePath.resolve(type.getDirectory()).resolve(namespace); + }); + } else + ModernFix.LOGGER.warn("Cannot cache resource pack for mod '{}' as it uses multiple base paths", modInfo.getId()); + } + + // this check wastes CPU time, it is checked later anyway + @Redirect(method = "getPath", at = @At(value = "INVOKE", target = "Lnet/fabricmc/fabric/impl/resource/loader/ModNioResourcePack;exists(Ljava/nio/file/Path;)Z"), remap = false) + private boolean checkExists(Path path) { + return true; + } + + // TODO might be redundant + @Inject(method = "getNamespaces", at = @At("HEAD"), cancellable = true) + private void useCacheForNamespaces(PackType type, CallbackInfoReturnable> cir) { + if(cacheEngine != null) { + Set namespaces = cacheEngine.getNamespaces(type); + if(namespaces != null) + cir.setReturnValue(namespaces); + } + } + + @Inject(method = "hasResource", at = @At(value = "HEAD"), cancellable = true) + private void useCacheForExistence(String path, CallbackInfoReturnable cir) { + if(cacheEngine != null) + cir.setReturnValue(this.cacheEngine.hasResource(path)); + } +}