package net.minecraft.server.packs; import com.google.common.base.Joiner; import com.google.common.collect.Sets; import com.mojang.logging.LogUtils; import java.io.IOException; import java.io.InputStream; import java.nio.file.DirectoryStream; import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.NoSuchFileException; import java.nio.file.NotDirectoryException; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.stream.Stream; import net.minecraft.FileUtil; import net.minecraft.Util; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.repository.Pack; import net.minecraft.server.packs.resources.IoSupplier; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; public class PathPackResources extends AbstractPackResources { private static final Logger LOGGER = LogUtils.getLogger(); private static final Joiner PATH_JOINER = Joiner.on("/"); private final Path root; public PathPackResources(PackLocationInfo location, Path root) { super(location); this.root = root; } @Nullable @Override public IoSupplier getRootResource(String... elements) { FileUtil.validatePath(elements); Path path = FileUtil.resolvePath(this.root, List.of(elements)); return Files.exists(path, new LinkOption[0]) ? IoSupplier.create(path) : null; } public static boolean validatePath(Path path) { return true; } @Nullable @Override public IoSupplier getResource(PackType packType, ResourceLocation location) { Path path = this.root.resolve(packType.getDirectory()).resolve(location.getNamespace()); return getResource(location, path); } @Nullable public static IoSupplier getResource(ResourceLocation location, Path path) { return FileUtil.decomposePath(location.getPath()).mapOrElse(list -> { Path path2 = FileUtil.resolvePath(path, list); return returnFileIfExists(path2); }, error -> { LOGGER.error("Invalid path {}: {}", location, error.message()); return null; }); } @Nullable private static IoSupplier returnFileIfExists(Path path) { return Files.exists(path, new LinkOption[0]) && validatePath(path) ? IoSupplier.create(path) : null; } @Override public void listResources(PackType packType, String namespace, String path, PackResources.ResourceOutput resourceOutput) { FileUtil.decomposePath(path).ifSuccess(list -> { Path pathx = this.root.resolve(packType.getDirectory()).resolve(namespace); listPath(namespace, pathx, list, resourceOutput); }).ifError(error -> LOGGER.error("Invalid path {}: {}", path, error.message())); } public static void listPath(String namespace, Path namespacePath, List decomposedPath, PackResources.ResourceOutput resourceOutput) { Path path = FileUtil.resolvePath(namespacePath, decomposedPath); try { Stream stream = Files.find(path, Integer.MAX_VALUE, (pathx, basicFileAttributes) -> basicFileAttributes.isRegularFile(), new FileVisitOption[0]); try { stream.forEach(path2 -> { String string2 = PATH_JOINER.join(namespacePath.relativize(path2)); ResourceLocation resourceLocation = ResourceLocation.tryBuild(namespace, string2); if (resourceLocation == null) { Util.logAndPauseIfInIde(String.format(Locale.ROOT, "Invalid path in pack: %s:%s, ignoring", namespace, string2)); } else { resourceOutput.accept(resourceLocation, IoSupplier.create(path2)); } }); } catch (Throwable var9) { if (stream != null) { try { stream.close(); } catch (Throwable var8) { var9.addSuppressed(var8); } } throw var9; } if (stream != null) { stream.close(); } } catch (NotDirectoryException | NoSuchFileException var10) { } catch (IOException var11) { LOGGER.error("Failed to list path {}", path, var11); } } @Override public Set getNamespaces(PackType type) { Set set = Sets.newHashSet(); Path path = this.root.resolve(type.getDirectory()); try { DirectoryStream directoryStream = Files.newDirectoryStream(path); try { for (Path path2 : directoryStream) { String string = path2.getFileName().toString(); if (ResourceLocation.isValidNamespace(string)) { set.add(string); } else { LOGGER.warn("Non [a-z0-9_.-] character in namespace {} in pack {}, ignoring", string, this.root); } } } catch (Throwable var9) { if (directoryStream != null) { try { directoryStream.close(); } catch (Throwable var8) { var9.addSuppressed(var8); } } throw var9; } if (directoryStream != null) { directoryStream.close(); } } catch (NotDirectoryException | NoSuchFileException var10) { } catch (IOException var11) { LOGGER.error("Failed to list path {}", path, var11); } return set; } @Override public void close() { } public static class PathResourcesSupplier implements Pack.ResourcesSupplier { private final Path content; public PathResourcesSupplier(Path content) { this.content = content; } @Override public PackResources openPrimary(PackLocationInfo location) { return new PathPackResources(location, this.content); } @Override public PackResources openFull(PackLocationInfo location, Pack.Metadata metadata) { PackResources packResources = this.openPrimary(location); List list = metadata.overlays(); if (list.isEmpty()) { return packResources; } else { List list2 = new ArrayList(list.size()); for (String string : list) { Path path = this.content.resolve(string); list2.add(new PathPackResources(location, path)); } return new CompositePackResources(packResources, list2); } } } }