package org.embeddedt.modernfix.mixin; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import net.minecraft.resources.ResourcePackType; import net.minecraft.resources.VanillaPack; import net.minecraft.util.ResourceLocation; import org.apache.commons.lang3.tuple.Pair; import org.embeddedt.modernfix.FileWalker; 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 org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.io.IOException; import java.nio.file.*; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.stream.Stream; @Mixin(VanillaPack.class) public class VanillaPackMixin { @Shadow @Final private static Map JAR_FILESYSTEM_BY_TYPE; private static LoadingCache, List> pathStreamLoadingCache = CacheBuilder.newBuilder() .build(FileWalker.INSTANCE); @Redirect(method = "getResources(Ljava/util/Collection;ILjava/lang/String;Ljava/nio/file/Path;Ljava/lang/String;Ljava/util/function/Predicate;)V", at = @At(value = "INVOKE", target = "Ljava/nio/file/Files;walk(Ljava/nio/file/Path;I[Ljava/nio/file/FileVisitOption;)Ljava/util/stream/Stream;")) private static Stream useCacheForLoading(Path path, int maxDepth, FileVisitOption[] fileVisitOptions) throws IOException { try { return pathStreamLoadingCache.get(Pair.of(path, maxDepth)).stream(); } catch (ExecutionException e) { if(e.getCause() instanceof IOException) /* generally always should be */ throw (IOException)e.getCause(); else throw new IOException(e); } } @Inject(method = "hasResource", at = @At(value = "INVOKE", target = "Ljava/lang/Class;getResource(Ljava/lang/String;)Ljava/net/URL;"), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) private void useCacheForExistence(ResourcePackType type, ResourceLocation location, CallbackInfoReturnable cir, String path) { FileSystem fs = JAR_FILESYSTEM_BY_TYPE.get(type); cir.setReturnValue(Files.exists(fs.getPath(path))); } }