From f2da18d62e20de6754a7d3c315de105687582092 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Fri, 2 Feb 2024 12:44:09 +0100
Subject: [PATCH] More provider source fixup

---
 patches/server/Paper-Plugins.patch | 80 +++++++++++++++++++-----------
 1 file changed, 51 insertions(+), 29 deletions(-)

diff --git a/patches/server/Paper-Plugins.patch b/patches/server/Paper-Plugins.patch
index 0f058ae011..5f86f5776a 100644
--- a/patches/server/Paper-Plugins.patch
+++ b/patches/server/Paper-Plugins.patch
@@ -3822,7 +3822,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +class PaperPluginInstanceManager {
 +
 +    private static final FileProviderSource FILE_PROVIDER_SOURCE = new FileProviderSource("File '%s'"::formatted);
-+    private static final DirectoryProviderSource DIRECTORY_PROVIDER_SOURCE = new DirectoryProviderSource();
 +
 +    private final List<Plugin> plugins = new ArrayList<>();
 +    private final Map<String, Plugin> lookupNames = new HashMap<>();
@@ -3904,8 +3903,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +        RuntimePluginEntrypointHandler<MultiRuntimePluginProviderStorage> runtimePluginEntrypointHandler = new RuntimePluginEntrypointHandler<>(new MultiRuntimePluginProviderStorage(this.dependencyTree));
 +        try {
-+            directory = DIRECTORY_PROVIDER_SOURCE.prepareContext(directory);
-+            DIRECTORY_PROVIDER_SOURCE.registerProviders(runtimePluginEntrypointHandler, directory);
++            List<Path> files = DirectoryProviderSource.INSTANCE.prepareContext(directory);
++            DirectoryProviderSource.INSTANCE.registerProviders(runtimePluginEntrypointHandler, files);
 +            runtimePluginEntrypointHandler.enter(Entrypoint.PLUGIN);
 +        } catch (Exception e) {
 +            // This should never happen, any errors that occur in this provider should instead be logged.
@@ -5489,55 +5488,54 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import com.mojang.logging.LogUtils;
 +import io.papermc.paper.plugin.entrypoint.EntrypointHandler;
 +import java.io.IOException;
-+import java.util.function.Consumer;
-+import org.slf4j.Logger;
-+
 +import java.nio.file.FileVisitOption;
 +import java.nio.file.Files;
 +import java.nio.file.Path;
++import java.util.ArrayList;
++import java.util.List;
++import java.util.function.Consumer;
++import org.slf4j.Logger;
 +
 +/**
 + * Loads all plugin providers in the given directory.
 + */
-+public class DirectoryProviderSource extends FileProviderSource {
++public class DirectoryProviderSource implements ProviderSource<Path, List<Path>> {
 +
 +    public static final DirectoryProviderSource INSTANCE = new DirectoryProviderSource();
++    private static final FileProviderSource FILE_PROVIDER_SOURCE = new FileProviderSource("Directory '%s'"::formatted);
 +    private static final Logger LOGGER = LogUtils.getClassLogger();
 +
-+    public DirectoryProviderSource() {
-+        super("Directory '%s'"::formatted);
-+    }
-+
 +    @Override
-+    public Path prepareContext(Path context) throws IOException {
++    public List<Path> prepareContext(Path context) throws IOException {
 +        // Symlink happy, create file if missing.
 +        if (!Files.isDirectory(context)) {
 +            Files.createDirectories(context);
 +        }
 +
++        final List<Path> files = new ArrayList<>();
 +        this.walkFiles(context, path -> {
 +            try {
-+                super.prepareContext(path);
++                files.add(FILE_PROVIDER_SOURCE.prepareContext(path));
 +            } catch (IllegalArgumentException ignored) {
 +                // Ignore illegal argument exceptions from jar checking
 +            } catch (IOException e) {
-+                throw new RuntimeException(e);
++                LOGGER.error("Error preparing plugin context: " + e.getMessage(), e);
 +            }
 +        });
-+        return context;
++        return files;
 +    }
 +
 +    @Override
-+    public void registerProviders(EntrypointHandler entrypointHandler, Path context) throws IOException {
-+        this.walkFiles(context, path -> {
++    public void registerProviders(EntrypointHandler entrypointHandler, List<Path> context) {
++        for (Path path : context) {
 +            try {
-+                super.registerProviders(entrypointHandler, path);
++                FILE_PROVIDER_SOURCE.registerProviders(entrypointHandler, path);
 +            } catch (IllegalArgumentException ignored) {
 +                // Ignore illegal argument exceptions from jar checking
 +            } catch (Exception e) {
 +                LOGGER.error("Error loading plugin: " + e.getMessage(), e);
 +            }
-+        });
++        }
 +    }
 +
 +    private void walkFiles(Path context, Consumer<Path> consumer) throws IOException {
@@ -5580,7 +5578,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +/**
 + * Loads a plugin provider at the given plugin jar file path.
 + */
-+public class FileProviderSource implements ProviderSource<Path> {
++public class FileProviderSource implements ProviderSource<Path, Path> {
 +
 +    private final Function<Path, String> contextChecker;
 +
@@ -5731,6 +5729,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import com.mojang.logging.LogUtils;
 +import io.papermc.paper.plugin.entrypoint.EntrypointHandler;
 +import java.nio.file.Path;
++import java.util.ArrayList;
 +import org.slf4j.Logger;
 +
 +import java.util.List;
@@ -5738,22 +5737,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +/**
 + * Registers providers at the provided files in the add-plugin argument.
 + */
-+public class PluginFlagProviderSource implements ProviderSource<List<Path>> {
++public class PluginFlagProviderSource implements ProviderSource<List<Path>, List<Path>> {
 +
 +    public static final PluginFlagProviderSource INSTANCE = new PluginFlagProviderSource();
++    private static final FileProviderSource FILE_PROVIDER_SOURCE = new FileProviderSource("File '%s' specified through 'add-plugin' argument"::formatted);
 +    private static final Logger LOGGER = LogUtils.getClassLogger();
-+    private final FileProviderSource providerSource = new FileProviderSource("File '%s' specified through 'add-plugin' argument"::formatted);
 +
 +    @Override
 +    public List<Path> prepareContext(List<Path> context) {
-+        return context;
++        final List<Path> files = new ArrayList<>();
++        for (Path path : context) {
++            try {
++                files.add(FILE_PROVIDER_SOURCE.prepareContext(path));
++            } catch (Exception e) {
++                LOGGER.error("Error preparing plugin context: " + e.getMessage(), e);
++            }
++        }
++        return files;
 +    }
 +
 +    @Override
 +    public void registerProviders(EntrypointHandler entrypointHandler, List<Path> context) {
 +        for (Path path : context) {
 +            try {
-+                this.providerSource.registerProviders(entrypointHandler, path);
++                FILE_PROVIDER_SOURCE.registerProviders(entrypointHandler, path);
 +            } catch (Exception e) {
 +                LOGGER.error("Error loading plugin: " + e.getMessage(), e);
 +            }
@@ -5775,13 +5782,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 + * A provider source is responsible for giving PluginTypes an EntrypointHandler for
 + * registering providers at.
 + *
++ * @param <I> input context
 + * @param <C> context
 + */
-+public interface ProviderSource<C> {
++public interface ProviderSource<I, C> {
 +
-+    C prepareContext(C context) throws IOException;
++    /**
++     * Prepares the context for use in {@link #registerProviders(EntrypointHandler, Object)}.
++     *
++     * @param context the context to prepare
++     * @return the prepared context, ready for use in {@link #registerProviders(EntrypointHandler, Object)}
++     * @throws IOException if an error occurs while preparing the context
++     */
++    C prepareContext(I context) throws IOException;
 +
-+    void registerProviders(EntrypointHandler entrypointHandler, C context) throws Throwable;
++    /**
++     * Uses the prepared context to register providers at the given entrypoint handler.
++     *
++     * @param entrypointHandler the entrypoint handler to register providers at
++     * @param context           the context to register providers at
++     * @throws Exception if an error occurs while registering providers
++     */
++    void registerProviders(EntrypointHandler entrypointHandler, C context) throws Exception;
 +}
 diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java b/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java
 new file mode 100644
@@ -6995,9 +7017,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +
 +    private static final Logger LOGGER = LogUtils.getClassLogger();
 +
-+    public static <C> void registerProvidersFromSource(ProviderSource<C> source, C context) {
++    public static <I, C> void registerProvidersFromSource(ProviderSource<I, C> source, I contextInput) {
 +        try {
-+            context = source.prepareContext(context);
++            C context = source.prepareContext(contextInput);
 +            source.registerProviders(LaunchEntryPointHandler.INSTANCE, context);
 +        } catch (Throwable e) {
 +            LOGGER.error(e.getMessage(), e);